#ifndef VPR_CONCRETE_TIMING_INFO_H
#define VPR_CONCRETE_TIMING_INFO_H

#include "vtr_log.h"
#include "timing_util.h"
#include "vpr_error.h"
#include "slack_evaluation.h"
#include "globals.h"

#include "tatum/report/graphviz_dot_writer.hpp"

void warn_unconstrained(std::shared_ptr<const tatum::TimingAnalyzer> analyzer);

//NOTE: These classes should not be used directly but created with the
//      make_*_timing_info() functions in timing_info.h, and used through
//      their abstract interfaces (SetupTimingInfo, HoldTimingInfo etc.)

template<class DelayCalc>
class ConcreteSetupTimingInfo : public SetupTimingInfo {
  public:
    //Constructors
    ConcreteSetupTimingInfo(std::shared_ptr<const tatum::TimingGraph> timing_graph_v,
                            std::shared_ptr<const tatum::TimingConstraints> timing_constraints_v,
                            std::shared_ptr<DelayCalc> delay_calc,
                            std::shared_ptr<tatum::SetupTimingAnalyzer> analyzer_v)
        : timing_graph_(timing_graph_v)
        , timing_constraints_(timing_constraints_v)
        , delay_calc_(delay_calc)
        , setup_analyzer_(analyzer_v)
        , slack_crit_(g_vpr_ctx.atom().nlist, g_vpr_ctx.atom().lookup) {
        //pass
    }

  public:
    //Accessors
    tatum::TimingPathInfo least_slack_critical_path() const override {
        if (least_slack_critical_path_.type() == tatum::TimingType::UNKOWN) {
            least_slack_critical_path_ = find_least_slack_critical_path_delay(*timing_constraints_, *setup_analyzer_);
        }
        return least_slack_critical_path_;
    }

    tatum::TimingPathInfo longest_critical_path() const override {
        if (longest_critical_path_.type() == tatum::TimingType::UNKOWN) {
            longest_critical_path_ = find_longest_critical_path_delay(*timing_constraints_, *setup_analyzer_);
        }
        return longest_critical_path_;
    }

    std::vector<tatum::TimingPathInfo> critical_paths() const override {
        return tatum::find_critical_paths(*timing_graph_, *timing_constraints_, *setup_analyzer_);
    }

    float setup_total_negative_slack() const override {
        if (std::isnan(sTNS_)) {
            sTNS_ = find_setup_total_negative_slack(*setup_analyzer_);
        }
        return sTNS_;
    }

    float setup_worst_negative_slack() const override {
        if (std::isnan(sWNS_)) {
            sWNS_ = find_setup_worst_negative_slack(*setup_analyzer_);
        }
        return sWNS_;
    }

    float setup_pin_slack(AtomPinId pin) const override {
        return slack_crit_.setup_pin_slack(pin);
    }

    float setup_pin_criticality(AtomPinId pin) const override {
        return slack_crit_.setup_pin_criticality(pin);
    }

    std::shared_ptr<const tatum::TimingAnalyzer> analyzer() const override {
        return setup_analyzer();
    }

    std::shared_ptr<const tatum::TimingGraph> timing_graph() const override {
        return timing_graph_;
    }

    std::shared_ptr<const tatum::TimingConstraints> timing_constraints() const override {
        return timing_constraints_;
    }

    std::shared_ptr<const tatum::SetupTimingAnalyzer> setup_analyzer() const override {
        return setup_analyzer_;
    }

  public:
    //Mutators
    void update() override {
        update_setup();

        if (warn_unconstrained_) {
            warn_unconstrained(analyzer());
        }

        //Reset cached values to invalid (calculated lazily in accessors)
        sTNS_ = std::numeric_limits<float>::quiet_NaN();
        sWNS_ = std::numeric_limits<float>::quiet_NaN();
        least_slack_critical_path_ = tatum::TimingPathInfo();
        longest_critical_path_ = tatum::TimingPathInfo();
    }

    void update_setup() override {
        //Update the arrival and required times and re-calculate slacks
        double sta_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            setup_analyzer_->update_setup_timing();

            sta_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        double slack_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            update_setup_slacks();

            slack_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        //Update global timing analysis stats
        auto& timing_ctx = g_vpr_ctx.mutable_timing();
        timing_ctx.stats.sta_wallclock_time += sta_wallclock_time;
        timing_ctx.stats.slack_wallclock_time += slack_wallclock_time;
        timing_ctx.stats.num_full_setup_updates += 1;
    }

    void update_setup_slacks() {
        slack_crit_.update_slacks_and_criticalities(*timing_graph_, *setup_analyzer_);
    }

    void set_warn_unconstrained(bool val) override { warn_unconstrained_ = val; }

  private:
    //Data
    std::shared_ptr<const tatum::TimingGraph> timing_graph_;
    std::shared_ptr<const tatum::TimingConstraints> timing_constraints_;
    std::shared_ptr<DelayCalc> delay_calc_;
    std::shared_ptr<tatum::SetupTimingAnalyzer> setup_analyzer_;

    SetupSlackCrit slack_crit_;

    //Cached values
    mutable float sTNS_ = std::numeric_limits<float>::quiet_NaN();
    mutable float sWNS_ = std::numeric_limits<float>::quiet_NaN();
    mutable tatum::TimingPathInfo least_slack_critical_path_;
    mutable tatum::TimingPathInfo longest_critical_path_;

    bool warn_unconstrained_ = true;

    typedef std::chrono::duration<double> dsec;
    typedef std::chrono::high_resolution_clock Clock;
};

template<class DelayCalc>
class ConcreteHoldTimingInfo : public HoldTimingInfo {
  public:
    //Constructors
    ConcreteHoldTimingInfo(std::shared_ptr<const tatum::TimingGraph> timing_graph_v,
                           std::shared_ptr<const tatum::TimingConstraints> timing_constraints_v,
                           std::shared_ptr<DelayCalc> delay_calc,
                           std::shared_ptr<tatum::HoldTimingAnalyzer> analyzer_v)
        : timing_graph_(timing_graph_v)
        , timing_constraints_(timing_constraints_v)
        , delay_calc_(delay_calc)
        , hold_analyzer_(analyzer_v)
        , slack_crit_(g_vpr_ctx.atom().nlist, g_vpr_ctx.atom().lookup) {
        //pass
    }

  public:
    //Accessors
    float hold_total_negative_slack() const override {
        return find_hold_total_negative_slack(*hold_analyzer_);
    }

    float hold_worst_negative_slack() const override {
        return find_hold_worst_negative_slack(*hold_analyzer_);
    }

    float hold_pin_slack(AtomPinId pin) const override {
        return slack_crit_.hold_pin_slack(pin);
    }

    float hold_pin_criticality(AtomPinId pin) const override {
        return slack_crit_.hold_pin_criticality(pin);
    }

    std::shared_ptr<const tatum::TimingAnalyzer> analyzer() const override { return hold_analyzer(); }
    std::shared_ptr<const tatum::HoldTimingAnalyzer> hold_analyzer() const override { return hold_analyzer_; }
    std::shared_ptr<const tatum::TimingGraph> timing_graph() const override { return timing_graph_; }
    std::shared_ptr<const tatum::TimingConstraints> timing_constraints() const override { return timing_constraints_; }

  public:
    //Mutators
    void update() override {
        update_hold();

        if (warn_unconstrained_) {
            warn_unconstrained(analyzer());
        }
    }

    void update_hold() override {
        double sta_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            hold_analyzer_->update_hold_timing();

            sta_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        double slack_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            update_hold_slacks();

            slack_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        //Update global timing analysis stats
        auto& timing_ctx = g_vpr_ctx.mutable_timing();
        timing_ctx.stats.sta_wallclock_time += sta_wallclock_time;
        timing_ctx.stats.slack_wallclock_time += slack_wallclock_time;
        timing_ctx.stats.num_full_hold_updates += 1;
    }

    void update_hold_slacks() {
        slack_crit_.update_slacks_and_criticalities(*timing_graph_, *hold_analyzer_);
    }

    void set_warn_unconstrained(bool val) override { warn_unconstrained_ = val; }

  private:
    //Data
    std::shared_ptr<const tatum::TimingGraph> timing_graph_;
    std::shared_ptr<const tatum::TimingConstraints> timing_constraints_;
    std::shared_ptr<DelayCalc> delay_calc_;
    std::shared_ptr<tatum::HoldTimingAnalyzer> hold_analyzer_;

    HoldSlackCrit slack_crit_;

    bool warn_unconstrained_ = true;

    typedef std::chrono::duration<double> dsec;
    typedef std::chrono::high_resolution_clock Clock;
};

template<class DelayCalc>
class ConcreteSetupHoldTimingInfo : public SetupHoldTimingInfo {
  public:
    //Constructors
    ConcreteSetupHoldTimingInfo(std::shared_ptr<const tatum::TimingGraph> timing_graph_v,
                                std::shared_ptr<const tatum::TimingConstraints> timing_constraints_v,
                                std::shared_ptr<DelayCalc> delay_calc,
                                std::shared_ptr<tatum::SetupHoldTimingAnalyzer> analyzer_v)
        : setup_timing_(timing_graph_v, timing_constraints_v, delay_calc, analyzer_v)
        , hold_timing_(timing_graph_v, timing_constraints_v, delay_calc, analyzer_v)
        , setup_hold_analyzer_(analyzer_v) {
        //pass
    }

  private:
    //Accessors

    //Setup related
    std::vector<tatum::TimingPathInfo> critical_paths() const override { return setup_timing_.critical_paths(); }
    tatum::TimingPathInfo least_slack_critical_path() const override { return setup_timing_.least_slack_critical_path(); }
    tatum::TimingPathInfo longest_critical_path() const override { return setup_timing_.longest_critical_path(); }

    float setup_total_negative_slack() const override { return setup_timing_.setup_total_negative_slack(); }
    float setup_worst_negative_slack() const override { return setup_timing_.setup_worst_negative_slack(); }

    float setup_pin_slack(AtomPinId pin) const override { return setup_timing_.setup_pin_slack(pin); }
    float setup_pin_criticality(AtomPinId pin) const override { return setup_timing_.setup_pin_criticality(pin); }

    std::shared_ptr<const tatum::SetupTimingAnalyzer> setup_analyzer() const override { return setup_timing_.setup_analyzer(); }

    //Hold related
    float hold_total_negative_slack() const override { return hold_timing_.hold_total_negative_slack(); }
    float hold_worst_negative_slack() const override { return hold_timing_.hold_worst_negative_slack(); }

    float hold_pin_slack(AtomPinId pin) const override { return hold_timing_.hold_pin_slack(pin); }
    float hold_pin_criticality(AtomPinId pin) const override { return hold_timing_.hold_pin_criticality(pin); }

    std::shared_ptr<const tatum::HoldTimingAnalyzer> hold_analyzer() const override { return hold_timing_.hold_analyzer(); }

    //Combined setup-hold related
    std::shared_ptr<const tatum::SetupHoldTimingAnalyzer> setup_hold_analyzer() const override { return setup_hold_analyzer_; }

    //TimingInfo related
    std::shared_ptr<const tatum::TimingAnalyzer> analyzer() const override { return setup_hold_analyzer(); }
    std::shared_ptr<const tatum::TimingGraph> timing_graph() const override {
        return setup_timing_.timing_graph();
        ;
    }
    std::shared_ptr<const tatum::TimingConstraints> timing_constraints() const override { return setup_timing_.timing_constraints(); }

  public:
    //Mutators

    //Update both setup and hold simultaneously
    //  This is more efficient than calling update_hold() and update_setup() separately, since
    //  it performs a single combined STA to update both setup and hold (instead of calling it
    //  twice).
    void update() override {
        double sta_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            setup_hold_analyzer_->update_timing();

            sta_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        double slack_wallclock_time = 0.;
        {
            auto start_time = Clock::now();

            setup_timing_.update_setup_slacks();
            hold_timing_.update_hold_slacks();

            slack_wallclock_time = std::chrono::duration_cast<dsec>(Clock::now() - start_time).count();
        }

        if (warn_unconstrained_) {
            warn_unconstrained(analyzer());
        }

        //Update global timing analysis stats
        auto& timing_ctx = g_vpr_ctx.mutable_timing();
        timing_ctx.stats.sta_wallclock_time += sta_wallclock_time;
        timing_ctx.stats.slack_wallclock_time += slack_wallclock_time;
        timing_ctx.stats.num_full_setup_hold_updates += 1;
    }

    //Update hold only
    void update_hold() override { hold_timing_.update_hold(); }

    //Update setup only
    void update_setup() override { setup_timing_.update_setup(); }

    void set_warn_unconstrained(bool val) override { warn_unconstrained_ = val; }

  private:
    ConcreteSetupTimingInfo<DelayCalc> setup_timing_;
    ConcreteHoldTimingInfo<DelayCalc> hold_timing_;
    std::shared_ptr<tatum::SetupHoldTimingAnalyzer> setup_hold_analyzer_;

    bool warn_unconstrained_ = true;

    typedef std::chrono::duration<double> dsec;
    typedef std::chrono::high_resolution_clock Clock;
};

//No-op version of timing info, useful for algorithms that query timing info when run with timing disabled
class ConstantTimingInfo : public SetupHoldTimingInfo {
  public:
    ConstantTimingInfo(const float criticality)
        : criticality_(criticality) {}

  public: //Accessors
    //Setup related
    std::vector<tatum::TimingPathInfo> critical_paths() const override { return std::vector<tatum::TimingPathInfo>(); }
    tatum::TimingPathInfo least_slack_critical_path() const override { return tatum::TimingPathInfo(); }
    tatum::TimingPathInfo longest_critical_path() const override { return tatum::TimingPathInfo(); }

    float setup_total_negative_slack() const override { return 0.; }
    float setup_worst_negative_slack() const override { return 0.; }

    float setup_pin_slack(AtomPinId /*pin*/) const override { return 0.; }

    float setup_pin_criticality(AtomPinId /*pin*/) const override {
        /*
         * Note: There is a big difference between setting pin criticality to 0 compared to 1.
         * If pin criticality is set to 0, then the current path delay is completely ignored
         * during optimization. By setting pin criticality to 1, the current path delay will
         * always be considered and optimized for.
         */
        return criticality_;
    }

    std::shared_ptr<const tatum::SetupTimingAnalyzer> setup_analyzer() const override { return nullptr; }

    //Hold related
    float hold_total_negative_slack() const override { return 0.; }
    float hold_worst_negative_slack() const override { return 0.; }

    float hold_pin_slack(AtomPinId /*pin*/) const override { return 0.; }
    float hold_pin_criticality(AtomPinId /*pin*/) const override { return 1.; }

    std::shared_ptr<const tatum::HoldTimingAnalyzer> hold_analyzer() const override { return nullptr; }

    //Combined setup-hold related
    std::shared_ptr<const tatum::SetupHoldTimingAnalyzer> setup_hold_analyzer() const override { return nullptr; }

    //TimingInfo related
    std::shared_ptr<const tatum::TimingAnalyzer> analyzer() const override { return nullptr; }
    std::shared_ptr<const tatum::TimingGraph> timing_graph() const override {
        return nullptr;
        ;
    }
    std::shared_ptr<const tatum::TimingConstraints> timing_constraints() const override { return nullptr; }

    void set_warn_unconstrained(bool /*val*/) override {}

  public: //Mutators
    void update() override {}
    void update_hold() override {}
    void update_setup() override {}

  private:
    float criticality_;

    typedef std::chrono::duration<double> dsec;
    typedef std::chrono::high_resolution_clock Clock;
};
#endif
