/**
  * @project Project
  * @brief   这是一个map, key为steady_lock, 存储数据最长保存一段时间, 也存在数量限制.
  * @author  lz
  * @data    2023/6/24
 **/
#pragma once

#include <iostream>
#include <chrono>
#include <map>

#include "error_code/error_code.hpp"

template<typename structT>
class MapStl {
public:
    using time_Map = std::map<std::chrono::steady_clock::time_point, structT>;
public:
    explicit MapStl(size_t st = 20, double durability = 3) {
        map_max_size = st;
        map_durability = durability;
    }

    Error_manager save(const structT &t) {
        if (m_map_T.size() > map_max_size) {
            m_map_T.erase(m_map_T.begin());
        }

        m_map_T.insert(std::pair<std::chrono::steady_clock::time_point, structT>(std::chrono::steady_clock::now(), t));

        update();

        return Error_code::SUCCESS;
    }

    Error_manager get(time_Map &t) {
        update();
        t = m_map_T;
        return Error_code::SUCCESS;
    }

    time_Map get() {
        update();
        return m_map_T;
    }

    Error_manager getLast(structT &t) {
        update();

        if (m_map_T.empty()) {
            return Error_code::FAILED;
        }

        t = m_map_T.end()->second;

        return Error_code::SUCCESS;
    }

    size_t size() {
        return m_map_T.size();
    }
private:
    void update() {
        auto now_t = std::chrono::steady_clock::now();

        std::chrono::duration<double> diff = now_t - m_map_T.begin()->first;
        while (diff.count() > map_durability) {
            m_map_T.erase(m_map_T.begin());
            if (m_map_T.size() > 0) {
                diff = now_t - m_map_T.begin()->first;
            } else {
                return;
            }
        }
    }

protected:
    std::map<std::chrono::steady_clock::time_point, structT> m_map_T;
    size_t map_max_size;
    double map_durability;

private:

};

class stableValue : public MapStl<double> {
public:
    // 方差求值
    double value() {
        double value = 0;
        if (m_map_T.size() > 1) {
            double av = 0;
            for (auto &t: m_map_T) {
                av += t.second;
            }
            av = av / m_map_T.size();
            printf("-----> av: %f\n", av);
            double var = 0;
            for (auto &t: m_map_T) {
                var += (t.second - av) * (t.second - av);
            }
            var = sqrt(var / m_map_T.size());
            printf("-----> var: %f\n", var);
            size_t num = 0;
            for (auto &t: m_map_T) {
                if (fabs(t.second - av) < var) {
                    value += t.second;
                    num++;
                }
            }
            printf("-----> value sum: %f, num: %ld\n", value, num);
            value = value / num;
        } else if (m_map_T.size() == 1) {
            value = m_map_T.begin()->second;
        } else {
            value = 0;
        }
        return value;
    }

private:

};

#define stable_value(value_, t_map_, member_) {         \
    value_ = 0                                          \
    if (t_map_.size() > 1) {                            \
        double av = 0;                                  \
        for (auto &t: t_map_) {                         \
            av += t.second.member_;                     \
        }                                               \
        av = av / t_map_.size();                        \
        double var = 0;                                 \
        for (auto &t: t_map_) {                         \
            var += (t.second.member_ - av) * (t.second.member_ - av);   \
        }                                               \
        var = sqrt(var / t_map_.size());                \
        size_t num = 0;                                 \
        for (auto &t: t_map_) {                         \
           if (t.second.member_ - av < var) {           \
                value_ += t.second.member_;             \
                num++;                                  \
           }                                            \
        }                                               \
        value_ = value_ / num;                          \
    } else if (t_map_.size() == 1) {                    \
        value_ = t_map_.begin()->second.member_;        \
    } else {                                            \
        value_ = 0;                                     \
    }                                                   \
}


