#include "lip_phy_stats.h"
#if LIP_PHY_USE_STATS

void lip_phy_stats_par_add_avg_val(t_lip_phy_par_avg_buf *par, uint16_t val, t_lip_phy_par_value *res) {
    uint16_t prev = par->arr[par->pos];
    par->arr[par->pos] = val;
    par->sum -= prev;
    par->sum += val;
    if (++par->pos == LIP_PHY_STATS_AVG_CNT)
        par->pos = 0;
    if (par->cnt < LIP_PHY_STATS_AVG_CNT)
        ++par->cnt;
    if (res) {
        if (par->cnt == LIP_PHY_STATS_AVG_CNT) {
            res->value = par->sum;
            res->flags |= LIP_PHY_STATS_PAR_FLAG_VALID;
        }
    }
}



void lip_phy_stats_par_add_wc(uint16_t val, t_lip_phy_par_value *res, bool pos) {
    if (res->flags & LIP_PHY_STATS_PAR_FLAG_SKIP_NEXT) {
        res->flags &= ~LIP_PHY_STATS_PAR_FLAG_SKIP_NEXT;
    } else {
        const uint16_t new_val = val << LIP_PHY_STATS_AVG_BITS;
        bool replace_req = !(res->flags & LIP_PHY_STATS_PAR_FLAG_VALID) || (res->flags & LIP_PHY_STATS_PAR_FLAG_STALE);
        if (!replace_req) {
            replace_req = pos ? new_val < res->value : new_val > res->value;
        }

        if (replace_req) {
            res->flags = LIP_PHY_STATS_PAR_FLAG_VALID;
            res->value = new_val;
        }
    }
}

void lip_phy_stats_par_add_cntr(uint16_t val, t_lip_phy_par_value *res) {
    if (res->flags & LIP_PHY_STATS_PAR_FLAG_SKIP_NEXT) {
        res->flags &= ~LIP_PHY_STATS_PAR_FLAG_SKIP_NEXT;
    } else {
        bool replace_req = !(res->flags & LIP_PHY_STATS_PAR_FLAG_VALID) || (res->flags & LIP_PHY_STATS_PAR_FLAG_STALE);
        if (replace_req) {
            res->flags = LIP_PHY_STATS_PAR_FLAG_VALID;
            res->value = val;
        } else {
            uint32_t new_val = res->value + val;
            if (new_val > LIP_PHY_STATS_PAR_VALUE_MAX)
                new_val = LIP_PHY_STATS_PAR_VALUE_MAX;
            res->value = new_val;
        }
    }
}


void lip_phy_stats_poll(t_lip_phy_ctx *ctx) {
    if (ctx->devinfo && ctx->devinfo->update_stats) {
        if (ctx->state.flags & LIP_PHY_STATE_FLAG_LINK_UP) {
#if LIP_PHY_STATS_WC_INTERVAL_MS > 0
            if (ltimer_expired(&ctx->stats.ctx.wc_stale_tmr)) {
                lip_phy_link_wc_stale(&ctx->stats, false);
            }
#endif
            /* Если fsm != 0, то не закончена процедура опроса статуса и нужно вызывать update_stats
             * для ее продвижения.
             * В случае fsm == 0, вызываем update_stats по таймеру, для запуска нового процесса получения
             * статистики */
            if ((ctx->stats.ctx.physpec.fsm != 0) || ltimer_expired(&ctx->stats.ctx.stats_check_tmr)) {
                ctx->devinfo->update_stats(&ctx->reg_acc, &ctx->state, &ctx->stats);
                ltimer_restart(&ctx->stats.ctx.stats_check_tmr);
            }
        }
    }
}

#endif

