#pragma once

#include <memory>
#include <unordered_map>
#include "common/Fields.h"
#include "Policy.h"

class Device;
class MqttClient;

struct TempHumUnit
{
    float temp {0};
    float hum {0};
    TempHumUnit(float temp, float hum) : temp(temp), hum(hum) {};
    TempHumUnit() {}
};

struct Fire40Unit
{
    //主控数量	R	uint16		1		0x0002
    //主控ID	R	uint16		1		0x0003
    int statusMain {0}; //主控状态	R	uint16		0：正常 1：预警 2：火警		0x0004
    //主控硬件版本	R	uint16[2]		主控硬件版本		0x0005~0x0006
    //主控软件版本	R	uint16[2]		主控软件版本		0x0007~0x0008
    //主电状态	R	uint16		0：使用市电 1：使用备电		0x0009
    //备电电流	R	uint32	0.1A			0x000A
    //备电电压	R	uint32	0.1V			0x000C
    //可用容量	R	uint32	0.01Ah			0x000E
    //可充放容量	R	uint32	0.01Ah			0x0010
    int usedAlarm {0};      //警铃是否使用	R	uint16				0x0012
    int statusAlarm {0};    //警铃状态	R	uint16		0：无效 1：掉线 2：正常 3：启动		0x0013
    int usedValve {0};      //瓶头阀是否使用	R	uint16				0x0014
    int statusValve {0};    //瓶头阀状态	R	uint16		0：无效 1：掉线 2：正常 3：启动		0x0015
    int usedMCP {0};        //手报是否使用	R	uint16				0x0016
    int statusMCP {0};      //手报状态	R	uint16		0：无效 1：掉线 2：正常 3：启动		0x0017 // Manual Call Point (MCP)
    //簇控制器数量	R	uint16				0x0018
    //复合探测器总数量	R	uint16				0x0019
    //烟雾探测器总数量	R	uint16				0x001A
    //压力探测器总数量	R	uint16				0x001B
    //吸气式探测器总数量	R	uint16				0x001C
    //PACK探测器总数量	R	uint16				0x001D
    //电池总数量	R	uint16				0x001E

};


struct CoolingUnit
{
    int powerOn {0};         //开关	    R	uint16		0：关机，1：开机		0x1003
    int mode {0};           //采样模式	R	uint16	    0-出水温度 1-电芯温度	0x1004
    int cooling {0};        //制冷状态	R	uint16		0：关闭, 1：启动		0x1005
    int heating {0};        //制热状态	R	uint16		0：关闭, 1：启动		0x1006
    int highTemp {0};       //高温告警	R	uint16		0：正常，1：告警		0x1007
    int lowTemp {0};        //低温告警	R	uint16		0：正常，1：告警		0x1008
    int highPressure {0};   //高压告警	R	uint16		0：正常，1：告警		0x1009
    int lowPressure {0};    //低压告警	R	uint16		0：正常，1：告警		0x100A
    //进水温度传感器	R	uint16		0：正常，1：告警		0x100B
    //出水温度传感器	R	uint16		0：正常，1：告警		0x100C
    //进水压力传感器	R	uint16		0：正常，1：告警		0x100D
    //出水压力传感器	R	uint16		0：正常，1：告警		0x100E
};

struct AircUnit
{
    int powerOn {0};        //开关	R	uint16		0：关机，1：开机
    int cooling {0};        //启动制冷指令	R	uint16		0：关闭, 1：启动
    int airSupply {0};      //启动送风指令	R	uint16		0：关闭, 1：启动
    int standby {0};        //启动待机指令	R	uint16		0：关闭, 1：启动
    int heating {0};        //启动加热指令	R	uint16		0：关闭, 1：启动
    int sensorAlarm {0};    //传感器故障	R	uint16		0：正常，1：告警
    int voltageAlarm {0};   //高低电压告警	R	uint16		0：正常，1：告警
    int tempAlarm {0};      //高低温告警	R	uint16		0：正常，1：告警
    int pressureAlarm {0};  //高低压告警	R	uint16		0：正常，1：告警
    int compressorAlarm {0};//压缩机告警	R	uint16		0：正常，1：告警

    //制冷点	R	int16	0.1℃			0x0003
    //制冷偏差	R	int16	0.1℃			0x0004
    //高温告警值	R	int16	0.1℃			0x0005
    //低温告警值	R	int16	0.1℃			0x0006
    //制热点	R	int16	0.1℃			0x0007
    //制热偏差	R	int16	0.1℃			0x0008
    int temp {0};   //当前温度	R	int16	0.1℃			0x0009
    int hum {0};    //当前湿度	R	int16	0.1℃			0x000A
    //除湿开启温度	R	int16	0.1℃			0x000B
    //除湿停止温度	R	int16	0.1℃			0x000C
    //除湿开启湿度	R	int16	0.1℃			0x000D
    //除湿停止湿度	R	int16	0.1℃			0x000E
};

class Station
{
public:
    Station();

    void setFields(Fields& fields);

    void addDevice(int deviceId, std::shared_ptr<Device> device);
    void addDevice(Fields& fields);
    std::shared_ptr<Device> getDevice(int deviceId);

    void groupDevice();
    
    std::shared_ptr<Device> getDeviceByType(int deviceType, std::string code);
    void getDeviceByType(int typeId, std::vector<std::shared_ptr<Device>>& res);
    int getDeviceCount(int category);
    void getDeviceByCategory(int category, std::vector<std::shared_ptr<Device>>& res);

    void setWorkMode(int modeId);

    void initMqtt();
    void polling();
    int64_t getPollingTS();
    void setGarewayWorkMode();
    void setGarewayParams();
    void checkDevice();

    string getGatewayMode();
    string getGatewayParam();

    void readAlert(std::shared_ptr<Device> device, std::string addr, int v, std::string text);
    void readEnergyData(int deviceNo, string addr, int val); // 电表
    void readEMSData(int deviceNo, string addr, int val);
    void readBMSData(int deviceNo, string addr, int val);
    void readChargeData(int deviceNo, string addr, int val);
    void readTHData(int deviceNo, string addr, int val);
    void readFire40Data(int deviceNo, string addr, int val);
    void readCoolingData(int deviceNo, string addr, int val);
    void readGatewayMode(int deviceNo, int mode, string p1, string p2, string p3);
    void readGatewayStatus(int deviceNo, int cdzStatus, int emuStatus, int tamStatus);

    // 台区电表的数据结构和其它不一致（不是点表）进行特殊处理
    void readTDData(int deviceNo, string str);

    void setCache(int datatype, std::vector<float>& vd);
    void cache();
    int posCache {0};

    void writeStatistic();
    int posDayStat {0};

    void predict();

    void writeDeviceData();

public:
    int stationId {};
    std::string name;
    std::string code;
    int status {0};
    std::string operationDate;
    //SysPolicy policy;
    std::string launchDate {};

    int err = 0;
    int online = 0;
    int running = 0;
    bool isConnected {false};

    int workMode {};  // 运行模式
    int runPolicyId {}; // 运行策略


    struct {
        int mode {-1};  // 运行模式
        std::string param1;
        std::string param2;
        std::string param3;

        int socMin {};  // 储能放电下限值 SOC  40038  (%, 0-99)
        int socMax {};  // 储能充电上限值 SOC  40039  (%:1-100)
        int capacity {}; // 台区变压器容量  40040  (KVA 160-1600)
        int powerSafe {};   // 安全输入功率  40041  (KW 0-400)
        int powerDischarge {};  // 储能最大放电功率  40042  (1KW 0-150)
        int powerCharge {};     // 储能最大充电功率  40043  (1KW 0-150)
        int status {}; // 运行状态:40044 (只读不写，0:无 1:高峰放电 2:低谷充电)
        int vtRatio ;// 台区电表变比 40045
        int backflow {}; // 防逆流回差  40058(1KW 10-300)
        int overload {}; // 防过载回差  40059(1KW 10-300)
    } gatewayParam;

    int cdzStatus{ -1 }; // 充电桩 1：在线，0：离线
    int emuStatus{ -1 }; // 储能 1：在线，0：离线
    int tamStatus{ -1 }; // 台区电表 1：在线，0：离线
    int pvStatus{ -1 };
    

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 储能相关数据 ===
    struct {
        int ts;         // 数据更新时间戳（通讯）
        int num = 1;    // 储能设备的数量（储能仓的个数）

        int status = 0; // 储能设备状态： 0：离线，1：空闲，2：充电，3：放电，9：故障

        int voltage = 0;
        int current = 0;
        int power = 0;
        float powerFactor = 0;

        vector<int> U; // 电压曲线（144个点位）
        vector<int> I; // 电流曲线（144个点位）
        vector<int> P; // 功率曲线（144个点位）

    } storage;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 充电相关数据 ===
    struct {
        int ts;         // 数据更新时间戳（通讯）
        int num = 1;    // 充电设备的数量
        int status = 0; // 充电设备状态： 0：离线，1：空闲，2：充电，9：故障

        struct {
            int isCharge = 0;
            int voltage = 0;
            int current = 0;
            int power = 0;
            int powerLimit = 0;
        } connector1;

        struct {
            int isCharge = 0;
            int voltage = 0;
            int current = 0;
            int power = 0;
            int powerLimit = 0;
        } connector2;

        vector<int> U; // 电压曲线（144个点位）
        vector<int> I; // 电流曲线（144个点位）
        vector<int> P; // 功率曲线（144个点位）
    } charge;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 光伏相关数据 ===
    struct {
        int ts;         // 数据更新时间戳（通讯）
        int status = 0; // 充电设备状态： 0：离线，1：空闲，2：发电，9：故障
        int voltage = 0;
        int current = 0;
        int power = 0;
        vector<int> U; // 电压曲线（144个点位）
        vector<int> I; // 电流曲线（144个点位）
        vector<int> P; // 功率曲线（144个点位）
    } pv;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 电网相关数据 ===
    struct {
        int status = 0; // 充电设备状态： 0：离线，1：空闲，2：发电，9：故障

        int voltage = 0;
        int current = 0;
        int power = 0;
        float powerFactor = 0;
        //vector<int> U; // 电压曲线（144个点位）
        //vector<int> I; // 电流曲线（144个点位）
        vector<int> P; // 功率曲线（144个点位）
    } grid;
    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 系统统计 ===
    // 累计发电量，单位：kWh
    double electGenTotal {};
    // 累计入网电量，单位：kWh
    double electGridTotal {};
    // 累计收益，单位：元
    double incomeTotal {};
    // 累计储能充电电量
    double electStorageIn {};
    // 累计储能放电电量
    double electStorageOut {};

    // 储能容量
    double capacity {};

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 环境 ===
    // 光照度
    double illuminance {};
    // 辐照度
    double irradiance {};
    // 风速
    double windspeed {};
    // 温度
    double temperature {};
    // 湿度
    double humidity {};
    int aircStatus {0};
    int coolingStatus {0};
    //double voltage {0};
    //double current {0};
    //double power {0};
    //double powerFactor {0};

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === 设备信息 ===
    std::unordered_map<int, std::shared_ptr<Device>> mapDevice;
    std::map<int, std::map<std::string, std::shared_ptr<Device>>> mapDeviceGroup;

    // 温湿度信息
    std::map<int, TempHumUnit> mapTempHumUnit;
    // 消防4.0信息
    std::map<int, Fire40Unit> mapFire40Unit;
    // 冷机信息
    std::map<int, CoolingUnit> mapCoolingUnit;
    // 空调信息
    std::map<int, AircUnit> mapAircUnit;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// === MQTT client
    std::shared_ptr<MqttClient> mqttCli {nullptr};


    struct {
        int64_t ts {0};

        float dayElectIn {0.0};    // 日充电电量	R	uint32	1kWh			0x002F
        float dayElectOut {0.0};   // 日放电电量	R	uint32	1kWh			0x0031
        float dayFeeIn {0.0};      // 日充电费用	R	uint32	1RMB			0x0033
        float dayFeeOut {0.0};     // 日放电费用	R	uint32	1RMB			0x0035
        float dayIncome {0.0};     // 日收益	R	int32	1RMB			0x0037
        
        float dayElectIn_J {0.0};   //日正向尖有功电能	R	uint32	1kWh			0x0039
        float dayElectIn_F {0.0};   //日正向峰有功电能	R	uint32	1kWh			0x003B
        float dayElectIn_P {0.0};   //日正向平有功电能	R	uint32	1kWh			0x003D
        float dayElectIn_G {0.0};   //日正向谷有功电能	R	uint32	1kWh			0x003F
        float dayElectIn_Total {0.0};//日正向总有功电能	R	uint32	1kWh			0x0041

        float dayElectOut_J {0.0};  //日反向尖有功电能	R	uint32	1kWh			0x0043
        float dayElectOut_F {0.0};  //日反向峰有功电能	R	uint32	1kWh			0x0045
        float dayElectOut_P {0.0};  //日反向平有功电能	R	uint32	1kWh			0x0047
        float dayElectOut_G {0.0};  //日反向谷有功电能	R	uint32	1kWh			0x0049
        float dayElectOut_Total {0.0};  //日反向总有功电能	R	uint32	1kWh			0x004B

        float totalElectIn {0.0};   // 总充电电量	R	uint32	1kWh			0x004D
        float totalElectOut {0.0};  // 总放电电量	R	uint32	1kWh			0x004F
        float totalFeeIn {0.0};     // 总充电费用	R	uint32	1RMB			0x0051
        float totalFeeOut {0.0};    // 总放电费用	R	uint32	1RMB			0x0053
        float totalIncome {0.0};    // 总收益	R	int32	1RMB			0x0055

        float totalElectIn_J {0.0};   //总正向尖有功电能	R	uint32	1kWh	0x0057
        float totalElectIn_F {0.0};   //总正向峰有功电能	R	uint32	1kWh	0x0059
        float totalElectIn_P {0.0};   //总正向平有功电能	R	uint32	1kWh	0x005B
        float totalElectIn_G {0.0};   //总正向谷有功电能	R	uint32	1kWh	0x005D
        float totalElectIn_Total {0.0};   //总正向总有功电能	R	uint32	1kWh	0x005F

        float totalElectOut_J {0.0};   //总反向尖有功电能	R	uint32	1kWh	0x0061
        float totalElectOut_F {0.0};   //总反向峰有功电能	R	uint32	1kWh	0x0063
        float totalElectOut_P {0.0};   //总反向平有功电能	R	uint32	1kWh	0x0065
        float totalElectOut_G {0.0};   //总反向谷有功电能	R	uint32	1kWh	0x0067
        float totalElectOut_Total {0.0};   //总反向总有功电能	R	uint32	1kWh	0x0069

    } statData;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    struct {
    } runtimeData;


    std::map<std::string, int64_t> mapAlertCache;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// 说明：从电表中读取对应数据：每间隔600秒（10分钟）缓存一个点位，存储到数据库，用于绘制一天的电曲线
    // 储能充电量缓存，key：位置索引（0->144），val：电量
    std::map<int, float> mapCacheElectIn;
    // 储能放电量缓存，key：位置索引（0->144），val：电量
    std::map<int, float> mapCacheElectOut;
    // 充电桩充电量缓存，key：位置索引（0->144），val：电量
    std::map<int, float> mapCacheElectCharger;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    /// 预测
    vector<int> predictStorageIn;
    vector<int> predictStorageOut;
    vector<int> predictCharge;
};