/*
 * 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/object.hh"

#include <algorithm>
#include <stack>

#include "systemc/core/event.hh"
#include "systemc/core/module.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_module.hh"
#include "systemc/ext/core/sc_simcontext.hh"

namespace sc_gem5
{

namespace
{

ObjectsIt
findObjectIn(Objects &objects, const std::string &name)
{
    ObjectsIt it;
    for (it = objects.begin(); it != objects.end(); it++)
        if (!strcmp((*it)->name(), name.c_str()))
            break;

    return it;
}

void
addObject(Objects *objects, sc_core::sc_object *object)
{
    objects->emplace(objects->end(), object);
}

void
popObject(Objects *objects, const std::string &name)
{
    ObjectsIt it = findObjectIn(*objects, name);
    assert(it != objects->end());
    std::swap(objects->back(), *it);
    objects->pop_back();
}

bool
nameIsUnique(Objects *objects, Events *events, const std::string &name)
{
    for (auto obj: *objects)
        if (!strcmp(obj->basename(), name.c_str()))
            return false;
    for (auto event: *events)
        if (!strcmp(event->basename(), name.c_str()))
            return false;
    return true;
}

} // anonymous namespace

Object::Object(sc_core::sc_object *_sc_obj) : Object(_sc_obj, nullptr) {}

Object::Object(sc_core::sc_object *_sc_obj, const char *obj_name) :
    _sc_obj(_sc_obj), _basename(obj_name ? obj_name : ""), parent(nullptr)
{
    if (_basename == "")
        _basename = ::sc_core::sc_gen_unique_name("object");

    parent = pickParentObj();

    Module *n = newModule();
    if (n) {
        // We are a module in the process of being constructed.
        n->finish(this);
    }

    std::string original_name = _basename;
    _basename = sc_gem5::pickUniqueName(parent, original_name);

    if (parent)
        addObject(&parent->_gem5_object->children, _sc_obj);
    else
        addObject(&topLevelObjects, _sc_obj);

    addObject(&allObjects, _sc_obj);

    sc_core::sc_object *sc_p = parent;
    std::string path = "";
    while (sc_p) {
        path = std::string(sc_p->basename()) + std::string(".") + path;
        sc_p = sc_p->get_parent_object();
    }

    if (_basename != original_name) {
        std::string message = path + original_name +
            ". Latter declaration will be renamed to " +
            path + _basename;
        SC_REPORT_WARNING(sc_core::SC_ID_INSTANCE_EXISTS_, message.c_str());
    }
    _name = path + _basename;
}

Object::Object(sc_core::sc_object *_sc_obj, const Object &arg) :
    Object(_sc_obj, arg._basename.c_str())
{}

Object &
Object::operator = (const Object &)
{
    return *this;
}

Object::~Object()
{
    // Promote all children to be top level objects.
    for (auto child: children) {
        addObject(&topLevelObjects, child);
        child->_gem5_object->parent = nullptr;
    }
    children.clear();

    for (auto event: events)
        Event::getFromScEvent(event)->clearParent();

    if (parent)
        popObject(&parent->_gem5_object->children, _name);
    else
        popObject(&topLevelObjects, _name);
    popObject(&allObjects, _name);
}

const char *
Object::name() const
{
    return _name.c_str();
}

const char *
Object::basename() const
{
    return _basename.c_str();
}

void
Object::print(std::ostream &out) const
{
    out << name();
}

void
Object::dump(std::ostream &out) const
{
    out << "name = " << name() << "\n";
    out << "kind = " << _sc_obj->kind() << "\n";
}

const std::vector<sc_core::sc_object *> &
Object::get_child_objects() const
{
    return children;
}

const std::vector<sc_core::sc_event *> &
Object::get_child_events() const
{
    return events;
}

sc_core::sc_object *Object::get_parent_object() const
{
    return parent;
}

bool
Object::add_attribute(sc_core::sc_attr_base &attr)
{
    return cltn.push_back(&attr);
}

sc_core::sc_attr_base *
Object::get_attribute(const std::string &attr)
{
    return cltn[attr];
}

sc_core::sc_attr_base *
Object::remove_attribute(const std::string &attr)
{
    return cltn.remove(attr);
}

void
Object::remove_all_attributes()
{
    cltn.remove_all();
}

int
Object::num_attributes() const
{
    return cltn.size();
}

sc_core::sc_attr_cltn &
Object::attr_cltn()
{
    return cltn;
}

const sc_core::sc_attr_cltn &
Object::attr_cltn() const
{
    return cltn;
}

sc_core::sc_simcontext *
Object::simcontext() const
{
    return sc_core::sc_get_curr_simcontext();
}

EventsIt
Object::addChildEvent(sc_core::sc_event *e)
{
    return events.emplace(events.end(), e);
}

void
Object::delChildEvent(sc_core::sc_event *e)
{
    EventsIt it = std::find(events.begin(), events.end(), e);
    assert(it != events.end());
    std::swap(*it, events.back());
    events.pop_back();
}

std::string
Object::pickUniqueName(std::string base)
{
    std::string seed = base;
    while (!nameIsUnique(&children, &events, base))
        base = ::sc_core::sc_gen_unique_name(seed.c_str());

    return base;
}

std::string
pickUniqueName(::sc_core::sc_object *parent, std::string base)
{
    if (parent)
        return Object::getFromScObject(parent)->pickUniqueName(base);

    std::string seed = base;
    while (!nameIsUnique(&topLevelObjects, &topLevelEvents, base))
        base = ::sc_core::sc_gen_unique_name(seed.c_str());

    return base;
}


Objects topLevelObjects;
Objects allObjects;

const std::vector<sc_core::sc_object *> &
getTopLevelScObjects()
{
    return topLevelObjects;
}

sc_core::sc_object *
findObject(const char *name, const Objects &objects)
{
    ObjectsIt it = findObjectIn(allObjects, name);
    return it == allObjects.end() ? nullptr : *it;
}

namespace
{

std::stack<sc_core::sc_object *> objParentStack;

} // anonymous namespace

sc_core::sc_object *
pickParentObj()
{
    if (!objParentStack.empty())
        return objParentStack.top();

    Process *p = scheduler.current();
    if (p)
        return p;

    return nullptr;
}

void pushParentObj(sc_core::sc_object *obj) { objParentStack.push(obj); }
void popParentObj() { objParentStack.pop(); }

} // namespace sc_gem5
