#include "trigger_engine.h"
#include <cstdio>

TriggerEngine::TriggerEngine() = default;

void TriggerEngine::configure(Edge edge, double threshold, Mode mode,
                               double pre_sec, double post_sec)
{
    edge_      = edge;
    threshold_ = threshold;
    mode_      = mode;
    pre_sec_   = pre_sec;
    post_sec_  = post_sec;
    has_prev_  = false;
}

void TriggerEngine::arm() {
    state_    = State::Armed;
    has_prev_ = false;
    std::fprintf(stderr, "[trigger] ARMED edge=%d thr=%.4f\n",
                 static_cast<int>(edge_), threshold_);
}

void TriggerEngine::disarm() {
    state_    = State::Idle;
    has_prev_ = false;
    std::fprintf(stderr, "[trigger] DISARMED\n");
}

bool TriggerEngine::feed_new(const double* new_t, const double* new_v, size_t n)
{
    if (state_ != State::Armed || n == 0) return false;

    for (size_t i = 0; i < n; ++i) {
        double cur = new_v[i];
        if (!has_prev_) {
            prev_val_ = cur;
            has_prev_ = true;
            continue;
        }

        bool fired = false;
        switch (edge_) {
        case Edge::Rising:  fired = (prev_val_ < threshold_ && cur >= threshold_); break;
        case Edge::Falling: fired = (prev_val_ > threshold_ && cur <= threshold_); break;
        case Edge::Either:
            fired = (prev_val_ < threshold_ && cur >= threshold_) ||
                    (prev_val_ > threshold_ && cur <= threshold_);
            break;
        }

        prev_val_ = cur;

        if (fired) {
            trig_time_ = new_t[i];
            state_     = State::Fired;
            std::fprintf(stderr, "[trigger] FIRED at t=%.6f\n", trig_time_);
            if (on_trigger) on_trigger();
            return true;
        }
    }
    return false;
}

bool TriggerEngine::post_complete(double current_latest_time) const
{
    if (state_ == State::Fired &&
        current_latest_time >= trig_time_ + post_sec_) {
        return true;
    }
    return false;
}
