/*
 * 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_EXT_CORE_SC_PORT_HH__
#define __SYSTEMC_EXT_CORE_SC_PORT_HH__

#include <vector>

#include "../utils/sc_report_handler.hh"
#include "sc_module.hh" // for sc_gen_unique_name
#include "sc_object.hh"

namespace sc_gem5
{

class Port;

};

namespace sc_core
{

class sc_interface;

enum sc_port_policy
{
    SC_ONE_OR_MORE_BOUND, // Default
    SC_ZERO_OR_MORE_BOUND,
    SC_ALL_BOUND
};

class sc_port_base : public sc_object
{
  public:
    sc_port_base(const char *name, int n, sc_port_policy p);
    virtual ~sc_port_base();

    void warn_unimpl(const char *func) const;

    int maxSize() const;
    int size() const;

    const char *kind() const { return "sc_port_base"; }

  protected:
    // Implementation defined, but depended on by the tests.
    void bind(sc_interface &);
    void bind(sc_port_base &);

    friend class ::sc_gem5::Module;

    // Implementation defined, but depended on by the tests.
    virtual int vbind(sc_interface &) = 0;
    virtual int vbind(sc_port_base &) = 0;

    virtual void before_end_of_elaboration() = 0;
    virtual void end_of_elaboration() = 0;
    virtual void start_of_simulation() = 0;
    virtual void end_of_simulation() = 0;

  private:
    friend class ::sc_gem5::Port;
    friend class ::sc_gem5::Kernel;

    virtual sc_interface *_gem5Interface(int n) const = 0;
    virtual void _gem5AddInterface(sc_interface *i) = 0;

    ::sc_gem5::Port *_gem5Port;
};

template <class IF>
class sc_port_b : public sc_port_base
{
  public:
    void operator () (IF &i) { bind(i); }
    void operator () (sc_port_b<IF> &p) { bind(p); }

    virtual void bind(IF &i) { sc_port_base::bind(i); }
    virtual void bind(sc_port_b<IF> &p) { sc_port_base::bind(p); }

    IF *
    operator -> ()
    {
        sc_assert(!_interfaces.empty());
        return _interfaces[0];
    }
    const IF *
    operator -> () const
    {
        sc_assert(!_interfaces.empty());
        return _interfaces[0];
    }

    IF *
    operator [] (int n)
    {
        sc_assert(_interfaces.size() > n);
        return _interfaces[n];
    }
    const IF *
    operator [] (int n) const
    {
        sc_assert(_interfaces.size() > n);
        return _interfaces[n];
    }

    sc_interface *
    get_interface()
    {
        sc_assert(!_interfaces.empty());
        return _interfaces[0];
    }
    const sc_interface *
    get_interface() const
    {
        sc_assert(!_interfaces.empty());
        return _interfaces[0];
    }

  protected:
    void before_end_of_elaboration() {}
    void end_of_elaboration() {}
    void start_of_simulation() {}
    void end_of_simulation() {}

    explicit sc_port_b(int n, sc_port_policy p) :
            sc_port_base(sc_gen_unique_name("port"), n, p)
    {}
    sc_port_b(const char *name, int n, sc_port_policy p) :
            sc_port_base(name, n, p)
    {}
    virtual ~sc_port_b() {}

    // Implementation defined, but depended on by the tests.
    int
    vbind(sc_interface &i)
    {
        IF *interface = dynamic_cast<IF *>(&i);
        if (!interface)
            return 2;
        sc_port_base::bind(*interface);
        return 0;
    }
    int
    vbind(sc_port_base &pb)
    {
        sc_port_b<IF> *p = dynamic_cast<sc_port_b<IF> *>(&pb);
        if (!p)
            return 2;
        sc_port_base::bind(*p);
        return 0;
    }

  private:
    std::vector<IF *> _interfaces;

    sc_interface *
    _gem5Interface(int n) const
    {
        sc_assert(_interfaces.size() > n);
        return _interfaces[n];
    }
    void
    _gem5AddInterface(sc_interface *i)
    {
        IF *interface = dynamic_cast<IF *>(i);
        sc_assert(interface);
        _interfaces.push_back(interface);
    }

    // Disabled
    sc_port_b() {}
    sc_port_b(const sc_port_b<IF> &) {}
    sc_port_b<IF> &operator = (const sc_port_b<IF> &) { return *this; }
};

template <class IF, int N=1, sc_port_policy P=SC_ONE_OR_MORE_BOUND>
class sc_port : public sc_port_b<IF>
{
  public:
    sc_port() : sc_port_b<IF>(N, P) {}
    explicit sc_port(const char *name) : sc_port_b<IF>(name, N, P) {}
    virtual ~sc_port() {}

    // Deprecated binding constructors.
    explicit sc_port(const IF &interface) : sc_port_b<IF>(N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(const_cast<IF &>(interface));
    }
    sc_port(const char *name, const IF &interface) : sc_port_b<IF>(name, N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(const_cast<IF &>(interface));
    }
    explicit sc_port(sc_port_b<IF> &parent) : sc_port_b<IF>(N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(parent);
    }
    sc_port(const char *name, sc_port_b<IF> &parent) :
        sc_port_b<IF>(name, N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(parent);
    }
    explicit sc_port(sc_port<IF, N, P> &parent) : sc_port_b<IF>(N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(parent);
    }
    sc_port(const char *name, sc_port<IF, N, P> &parent) :
        sc_port_b<IF>(name, N, P)
    {
        this->warn_unimpl(__PRETTY_FUNCTION__);
        // Should warn that these are deprecated. See Accellera sc_port.h.
        sc_port_b<IF>::bind(parent);
    }

    virtual const char *kind() const { return "sc_port"; }

  private:
    // Disabled
    sc_port(const sc_port<IF, N, P> &) {}
    sc_port<IF, N, P> &operator = (const sc_port<IF, N, P> &) { return *this; }
};

} // namespace sc_core

#endif  //__SYSTEMC_EXT_CORE_SC_PORT_HH__
