/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/event.hh"

#include <algorithm>
#include <cstring>
#include <utility>

#include "base/logging.hh"
#include "sim/core.hh"
#include "systemc/core/module.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/core/sc_module.hh"

namespace sc_gem5
{

Event::Event(sc_core::sc_event *_sc_event, bool internal) :
    Event(_sc_event, nullptr, internal)
{}

Event::Event(sc_core::sc_event *_sc_event, const char *_basename_cstr,
        bool internal) :
    _sc_event(_sc_event), _basename(_basename_cstr ? _basename_cstr : ""),
    _inHierarchy(!internal), delayedNotify([this]() { this->notify(); }),
    _triggeredStamp(~0ULL)
{
    if (_basename == "" && ::sc_core::sc_is_running())
        _basename = ::sc_core::sc_gen_unique_name("event");

    parent = internal ? nullptr : pickParentObj();

    if (internal) {
        _basename = globalNameGen.gen(_basename);
        _name = _basename;
    } else {
        std::string original_name = _basename;
        _basename = pickUniqueName(parent, _basename);

        if (parent) {
            Object *obj = Object::getFromScObject(parent);
            obj->addChildEvent(_sc_event);
        } else {
            topLevelEvents.emplace(topLevelEvents.end(), _sc_event);
        }

        std::string path = parent ? (std::string(parent->name()) + ".") : "";

        if (original_name != "" && _basename != original_name) {
            std::string message = path + original_name +
                ". Latter declaration will be renamed to " +
                path + _basename;
            SC_REPORT_WARNING("(W505) object already exists", message.c_str());
        }

        _name = path + _basename;
    }

    allEvents.emplace(allEvents.end(), _sc_event);

    // Determine if we're in the hierarchy (created once initialization starts
    // means no).
}

Event::~Event()
{
    if (parent) {
        Object *obj = Object::getFromScObject(parent);
        obj->delChildEvent(_sc_event);
    } else if (inHierarchy()) {
        EventsIt it = find(topLevelEvents.begin(), topLevelEvents.end(),
                           _sc_event);
        assert(it != topLevelEvents.end());
        std::swap(*it, topLevelEvents.back());
        topLevelEvents.pop_back();
    }

    EventsIt it = findEvent(_name);
    std::swap(*it, allEvents.back());
    allEvents.pop_back();

    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

const std::string &
Event::name() const
{
    return _name;
}

const std::string &
Event::basename() const
{
    return _basename;
}

bool
Event::inHierarchy() const
{
    return _inHierarchy;
}

sc_core::sc_object *
Event::getParentObject() const
{
    return parent;
}

void
Event::notify(StaticSensitivities &senses)
{
    for (auto s: senses)
        s->notify(this);
}

void
Event::notify(DynamicSensitivities &senses)
{
    int size = senses.size();
    int pos = 0;
    while (pos < size) {
        if (senses[pos]->notify(this))
            senses[pos] = senses[--size];
        else
            pos++;
    }
    senses.resize(size);
}

void
Event::notify()
{
    if (scheduler.inUpdate()) {
        SC_REPORT_ERROR("(E521) immediate notification is not allowed "
                "during update phase or elaboration", "");
    }

    // An immediate notification overrides any pending delayed notification.
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);

    _triggeredStamp = scheduler.changeStamp();
    notify(staticSenseMethod);
    notify(dynamicSenseMethod);
    notify(staticSenseThread);
    notify(dynamicSenseThread);
}

void
Event::notify(const sc_core::sc_time &t)
{
    if (delayedNotify.scheduled()) {
        if (scheduler.delayed(t) >= delayedNotify.when())
            return;

        scheduler.deschedule(&delayedNotify);
    }
    scheduler.schedule(&delayedNotify, t);
}

void
Event::notifyDelayed(const sc_core::sc_time &t)
{
    if (delayedNotify.scheduled()) {
        SC_REPORT_ERROR("(E531) notify_delayed() cannot be called on events "
                "that have pending notifications", "");
    }
    notify(t);
}

void
Event::cancel()
{
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

bool
Event::triggered() const
{
    return _triggeredStamp == scheduler.changeStamp();
}

void
Event::clearParent()
{
    if (!parent)
        return;
    Object::getFromScObject(parent)->delChildEvent(sc_event());
    parent = nullptr;
    topLevelEvents.emplace(topLevelEvents.end(), sc_event());
}

Events topLevelEvents;
Events allEvents;

EventsIt
findEvent(const std::string &name)
{
    EventsIt it;
    for (it = allEvents.begin(); it != allEvents.end(); it++)
        if (!strcmp((*it)->name(), name.c_str()))
            break;

    return it;
}

} // namespace sc_gem5
