/*
 * 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
 */

#ifndef __SYSTEMC_CORE_EVENT_HH__
#define __SYSTEMC_CORE_EVENT_HH__

#include <list>
#include <string>
#include <vector>

#include "sim/eventq.hh"
#include "systemc/core/list.hh"
#include "systemc/core/object.hh"
#include "systemc/core/process.hh"
#include "systemc/core/sched_event.hh"
#include "systemc/core/sensitivity.hh"
#include "systemc/ext/core/sc_prim.hh"
#include "systemc/ext/core/sc_time.hh"

namespace sc_core
{

class sc_event;

} // namespace sc_core

namespace sc_gem5
{

typedef std::vector<sc_core::sc_event *> Events;

class Sensitivity;

class Event
{
  public:
    Event(sc_core::sc_event *_sc_event);
    Event(sc_core::sc_event *_sc_event, const char *_basename);

    ~Event();

    sc_core::sc_event *sc_event() { return _sc_event; }

    const std::string &name() const;
    const std::string &basename() const;
    bool inHierarchy() const;
    sc_core::sc_object *getParentObject() const;

    void notify(StaticSensitivities &senses);
    void notify(DynamicSensitivities &senses);

    void notify();
    void notify(const sc_core::sc_time &t);
    void
    notify(double d, sc_core::sc_time_unit &u)
    {
        notify(sc_core::sc_time(d, u));
    }
    void cancel();

    bool triggered() const;

    static Event *
    getFromScEvent(sc_core::sc_event *e)
    {
        return e->_gem5_event;
    }

    static const Event *
    getFromScEvent(const sc_core::sc_event *e)
    {
        return e->_gem5_event;
    }

    void
    addSensitivity(StaticSensitivity *s) const
    {
        // Insert static sensitivities in reverse order to match Accellera's
        // implementation.
        auto &senses = s->ofMethod() ? staticSenseMethod : staticSenseThread;
        senses.insert(senses.begin(), s);
    }
    void
    delSensitivity(StaticSensitivity *s) const
    {
        auto &senses = s->ofMethod() ? staticSenseMethod : staticSenseThread;
        for (auto &t: senses) {
            if (t == s) {
                t = senses.back();
                senses.pop_back();
                break;
            }
        }
    }
    void
    addSensitivity(DynamicSensitivity *s) const
    {
        auto &senses = s->ofMethod() ? dynamicSenseMethod : dynamicSenseThread;
        senses.push_back(s);
    }
    void
    delSensitivity(DynamicSensitivity *s) const
    {
        auto &senses = s->ofMethod() ? dynamicSenseMethod : dynamicSenseThread;
        for (auto &t: senses) {
            if (t == s) {
                t = senses.back();
                senses.pop_back();
                break;
            }
        }
    }

  private:
    sc_core::sc_event *_sc_event;

    std::string _basename;
    std::string _name;
    bool _inHierarchy;

    sc_core::sc_object *parent;

    ScEvent delayedNotify;

    mutable StaticSensitivities staticSenseMethod;
    mutable StaticSensitivities staticSenseThread;
    mutable DynamicSensitivities dynamicSenseMethod;
    mutable DynamicSensitivities dynamicSenseThread;
};

extern Events topLevelEvents;
extern Events allEvents;

EventsIt findEvent(const std::string &name);

} // namespace sc_gem5

#endif  //__SYSTEMC_CORE_EVENT_HH__
