//
// Created by xin on 25-4-2.
//

#include "TemperatureRegulator.h"
#include "logout.h"
#include "sunupanddown.h"
 TemperatureRegulator *g_tempretureRegulator;
TemperatureRegulator::TemperatureRegulator(){

     g_tempretureRegulator=this;
}
/*
"PortName": "ttyS2",
    "BaudRate": 115200,
    "Pin": {
      "TG": {
        "Pin_H": 2,
        "Pin_L": 3
        },
      "Fan": {
        "Pin": 10
        },
      "HOT": {
        "Pin": 7
       }
    },
    "Constant_Temperature": {
        "CoolBegin_Temp_Insight": 20,
        "CoolBegin_Diff_Temp": 5,
"HeatingBegin_Temp_Insight": 0,
      "IsCoolInDaylight": false
    },
    "Location": {
      "latitude": 0,
      "longitude": 0
    },
    "IndexInfo": {
      "Insight": [{"x":7,"y":1},{"x":8,"y":1}],
      "Outside": [{"x":1,"y":1},{"x":2,"y":1}]
    }

 **/
void TemperatureRegulator::setconfig(json jconfig) {
    QString Port_Name="ttyS2";
    int BaudRate=115200;

    if (jconfig.contains("PortName")) {
        Port_Name=QString::fromStdString(jconfig["PortName"]);
    }
    if (jconfig.contains("BaudRate")) {
        BaudRate=jconfig["BaudRate"];
    }
    m_TemperaTureWoker=new TemperaTureWoker();
    m_TemperaTureWoker->OpenCom(Port_Name,BaudRate);
    // int pin1_H=7;
    // int pin1_L=10;
    // int pin2_H=2;
    // int pin2_L=4;
    // if (jconfig.contains("Pin")) {
    //     if (jconfig["Pin"].contains("")) {
    //         if (jconfig["Pin"]["TG"].contains("Pin_H")) {
    //             pin1_H=jconfig["Pin"]["TG"]["Pin_H"];
    //         }
    //         if (jconfig["Pin"]["TG"].contains("Pin_L")) {
    //             pin1_L=jconfig["Pin"]["TG"]["Pin_L"];
    //         }
    //     }
    //     if (jconfig["Pin"].contains("Fan")) {
    //         if (jconfig["Pin"]["Fan"].contains("Pin")) {
    //             pin2_H=jconfig["Pin"]["Fan"]["Pin"];
    //         }
    //     }
    //     if (jconfig["Pin"].contains("HOT")) {
    //         if (jconfig["Pin"]["HOT"].contains("Pin")) {
    //             pin2_L=jconfig["Pin"]["HOT"]["Pin"];
    //         }
    //     }
    // }
    /*
    *     "Pin": {
      "COOLER": {
        "Pin": 24
        },
      "Fan": {
        "Pin_H": 3,
        "Pin_L": 2
        },
      "HOT": {
        "Pin": 19
       },
      "WINDOWS": {
        "Pin_H": 7,
        "Pin_L": 10,
        "WaitTime": 40
       }
    },
     */
    int Cooler_Pin_EN=24;
    int Fan_Pin_H=3;
    int Fan_Pin_L=2;
    int Hot_Pin_EN=19;
    int Windows_Pin_H=7;
    int Windows_Pin_L=10;
    int Windows_WaitTime=40;
    if (jconfig.contains("Pin")) {
        if (jconfig["Pin"].contains("COOLER")) {
            if (jconfig["Pin"]["COOLER"].contains("Pin")) {
                Cooler_Pin_EN=jconfig["Pin"]["COOLER"]["Pin"];
            }
        }
        if (jconfig["Pin"].contains("Fan")) {
            if (jconfig["Pin"]["Fan"].contains("Pin_H")) {
                Fan_Pin_H=jconfig["Pin"]["Fan"]["Pin_H"];
            }
            if (jconfig["Pin"]["Fan"].contains("Pin_L")) {
                Fan_Pin_L=jconfig["Pin"]["Fan"]["Pin_L"];
            }
        }
        if (jconfig["Pin"].contains("HOT")) {
            if (jconfig["Pin"]["HOT"].contains("Pin")) {
                Hot_Pin_EN=jconfig["Pin"]["HOT"]["Pin"];
            }
        }
        if (jconfig["Pin"].contains("WINDOWS")) {
            if (jconfig["Pin"]["WINDOWS"].contains("Pin_H")) {
                Windows_Pin_H=jconfig["Pin"]["WINDOWS"]["Pin_H"];
            }
            if (jconfig["Pin"]["WINDOWS"].contains("Pin_L")) {
                Windows_Pin_L=jconfig["Pin"]["WINDOWS"]["Pin_L"];
            }
            if (jconfig["Pin"]["WINDOWS"].contains("WaitTime")) {
                Windows_WaitTime=jconfig["Pin"]["WINDOWS"]["WaitTime"];
            }
        }
    }


    m_TG_Manager=new TG_Manager();
    m_TG_Manager->SetPin_V2(Windows_Pin_H,Windows_Pin_L,Cooler_Pin_EN,Hot_Pin_EN,Fan_Pin_H,Fan_Pin_L);
    m_TG_Manager->Set_Waite_time_for_Windows(Windows_WaitTime);

    // m_TG_Manager->SetPin(pin1_H,pin1_L,pin2_H,pin2_L);
    if (jconfig.contains("Constant_Temperature")) {
        if (jconfig["Constant_Temperature"].contains("CoolBegin_Temp_Insight")) {
            m_CoolBegin_Temp_Insight=jconfig["Constant_Temperature"]["CoolBegin_Temp_Insight"];
        }
        if (jconfig["Constant_Temperature"].contains("CoolBegin_Diff_Temp")) {
           m_CoolBegin_Diff_Temp=jconfig["Constant_Temperature"]["CoolBegin_Diff_Temp"];
        }
        if (jconfig["Constant_Temperature"].contains("HeatingBegin_Temp_Insight")) {
            m_HeatingBegin_Temp_Insight=jconfig["Constant_Temperature"]["HeatingBegin_Temp_Insight"];
        }
        if (jconfig["Constant_Temperature"].contains("IsCoolInDaylight")) {
            m_IsCoolInDaylight=jconfig["Constant_Temperature"]["IsCoolInDaylight"].get<bool>();
        }
    }



    if (jconfig.contains("Location")) {
        if (jconfig["Location"].contains("latitude")) {
            m_Latitude=jconfig["Location"]["latitude"];
        }
        if (jconfig["Location"].contains("longitude")) {
            m_Longitude=jconfig["Location"]["longitude"];
        }
    }
    if (jconfig.contains("IndexInfo")) {
        if (jconfig["IndexInfo"].contains("Insight")) {
            for (int i = 0; i < jconfig["IndexInfo"]["Insight"].size(); ++i) {
                int x=jconfig["IndexInfo"]["Insight"][i]["x"];
                int y=jconfig["IndexInfo"]["Insight"][i]["y"];
                addTargetIndex(x,y,INSIGHT_TEMPERATURE);
            }
        }
        if (jconfig["IndexInfo"].contains("Outside")) {
            for (int i = 0; i < jconfig["IndexInfo"]["Outside"].size(); ++i) {
                int x=jconfig["IndexInfo"]["Outside"][i]["x"];
                int y=jconfig["IndexInfo"]["Outside"][i]["y"];
                addTargetIndex(x,y,OUTSIGHT_TEMPERATURE);
            }
        }
    }








    isinit=true;




}

void TemperatureRegulator::SetTartGetX_Y(int x,int y){
    m_target_index=x;
    m_target_indey=y;

}

void TemperatureRegulator::addTargetIndex(int x, int y,int Data_type) {
    //判断数据有效性
    if (x<0||y<0) {
        logout("TemperatureRegulator","addTargetIndex error little than 0",6);
        return;
    }
    if (x>7||y>7) {
        logout("TemperatureRegulator","addTargetIndex error Big",6);
        return;
    }
   switch (Data_type) {
       case INSIGHT_TEMPERATURE: {
           m_target_index_of_insight.push_back({x-1,y-1});
              break;
       }
       case OUTSIGHT_TEMPERATURE: {
              m_target_index_of_outsight.push_back({x-1,y-1});
              break;
         }
       default: {
           break;
       }
   }
}

float TemperatureRegulator::GetMax_of_Vector(int Data_type) {
    switch (Data_type) {
        case INSIGHT_TEMPERATURE: {
            float max=0;
            for (int i = 0; i < m_target_index_of_insight.size(); ++i) {
                int x=m_target_index_of_insight[i].x;
                int y=m_target_index_of_insight[i].y;
                if (m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x]>max) {
                    max=m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x];
                }
            }
            return max;
        }
        case OUTSIGHT_TEMPERATURE: {
            float max=0;
            for (int i = 0; i < m_target_index_of_outsight.size(); ++i) {
                int x=m_target_index_of_outsight[i].x;
                int y=m_target_index_of_outsight[i].y;
                if (m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x]>max) {
                    max=m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x];
                }
            }
            return max;
        }
        default: {
            return 0;
        }
    }
}

float TemperatureRegulator::GetMin_of_Vector(int Data_type) {
    switch (Data_type) {
        case INSIGHT_TEMPERATURE: {

            float min=100;
            for (int i = 0; i < m_target_index_of_insight.size(); ++i) {
                int x=m_target_index_of_insight[i].x;
                int y=m_target_index_of_insight[i].y;
                if (m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x]<min) {
                    min=m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x];
                }
            }
            return min;
        }
        case OUTSIGHT_TEMPERATURE: {
            float min=100;
            for (int i = 0; i < m_target_index_of_outsight.size(); ++i) {
                int x=m_target_index_of_outsight[i].x;
                int y=m_target_index_of_outsight[i].y;
                if (m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x]<min) {
                    min=m_TemperaTureWoker->m_Tempreaturegroups[y].tempera[x];
                }
            }
            return min;
        }
        default: {
            return 0;
        }
    }
}

void TemperatureRegulator::init(){




}

void TemperatureRegulator::PanduanCooling() {

}
int timesforlog=0;
void TemperatureRegulator::loopsample() {
    if (!isinit) return;
    m_TemperaTureWoker->ReadTempreature();
    // todo 用savedata函数记录temperature
    QString datastr="";
    for (int i = 0; i < m_TemperaTureWoker->m_Tempreaturegroups.size(); ++i) {
        for (int j = 0; j < 8; ++j) {
            datastr+=QString::number(m_TemperaTureWoker->m_Tempreaturegroups[i].tempera[j])+",";
        }
    }
    saveDataToFile("Tempratrue",datastr);
    QDateTime currentTime=QDateTime::currentDateTime();
    int year=currentTime.date().year();
    int month=currentTime.date().month();
    int day=currentTime.date().day();
    int nowhour=currentTime.time().hour();
    int nowminute=currentTime.time().minute();
    long nowminuteofday=nowhour*60+nowminute;
    SunInfo sunInfo=calculateSunriseSunset(year,month,day,m_Latitude,m_Longitude);
    float sunrise_minte=sunInfo.sunrise_h*60+sunInfo.sunrise_m;
    float sunset_minte=sunInfo.sunset_h*60+sunInfo.sunset_m;

    if (timesforlog%60==0) {
        logout("Temp","now minute of day is "+QString::number(nowminuteofday)+
               " sunrise minute is "+QString::number(sunrise_minte)+
               " sunset minute is "+QString::number(sunset_minte),6);

    }
    timesforlog++ ;
    //排除一天的前一个小时
   if (nowminuteofday>60) {
       if (last_time_in_today_minute<sunrise_minte&&nowminuteofday>=sunrise_minte&&nowminuteofday<sunset_minte) {
           //sunrise happened
           logout("Temp","sunrise happened",6);
           m_TG_Manager->Windows_Close();
         //  m_TG_Manager->Stop();
       }
       if (last_time_in_today_minute<sunset_minte&&nowminuteofday>=sunset_minte) {
           //sunset happened
           logout("Temp","sunset happened",6);
           m_TG_Manager->Windows_Open();
          // m_TG_Manager->Stop();
       }
   }




    last_time_in_today_minute=nowminuteofday;
};
void TemperatureRegulator::loop(){
    if (!isinit) return;
    m_TemperaTureWoker->ReadTempreature();
    // todo 用savedata函数记录temperature
    QString datastr="";
    for (int i = 0; i < m_TemperaTureWoker->m_Tempreaturegroups.size(); ++i) {
        for (int j = 0; j < 8; ++j) {
            datastr+=QString::number(m_TemperaTureWoker->m_Tempreaturegroups[i].tempera[j])+",";
        }
    }
    saveDataToFile("Tempratrue",datastr);
    QDateTime currentTime=QDateTime::currentDateTime();
    int year=currentTime.date().year();
    int month=currentTime.date().month();
    int day=currentTime.date().day();
    int nowhour=currentTime.time().hour();
    int nowminute=currentTime.time().minute();
    long nowminuteofday=nowhour*60+nowminute;
    SunInfo sunInfo=calculateSunriseSunset(year,month,day,m_Latitude,m_Longitude);
    float sunrise_minte=sunInfo.sunrise_h*60+sunInfo.sunrise_m;
    float sunset_minte=sunInfo.sunset_h*60+sunInfo.sunset_m;
    //如果时白天（前后个加15分钟误差）
    if (nowminuteofday>sunrise_minte+15&&nowminuteofday<sunset_minte-15) //白天
    {
        if (m_IsCoolInDaylight) {
            // 白天 当内外温差大于m_CoolBegin_Diff_Temp 且当前insight温度大于设定起始值 可以开始降温
            //第一步 获取内部最大温度
            float maxinsighttemp=GetMax_of_Vector(INSIGHT_TEMPERATURE);
            //第二步 获取外部最小温度
            float minoutsighttemp=GetMin_of_Vector(OUTSIGHT_TEMPERATURE);
            // 计算diff
            float diff=maxinsighttemp-minoutsighttemp;
            // 如果内外温差大于预设值
            if (diff>m_CoolBegin_Diff_Temp) {
                // 如果当前insight温度大于设定起始值
                if (maxinsighttemp>m_CoolBegin_Temp_Insight) {
                    m_TG_Manager->Cooling(true);
                    logout("Temp","current max insight temp is "+QString::number(maxinsighttemp),6);
                } else {
                    m_TG_Manager->Stop();
                    logout("Temp","current max insight temp is "+QString::number(maxinsighttemp),6);
                }
            } else {
                m_TG_Manager->Stop();
                logout("Temp","current diff is "+QString::number(diff),6);
            }
        }





        //如果 开始加热温度高于开始降温温度 说明参数设置有问题 推出
        if (m_CoolBegin_Temp_Insight<m_HeatingBegin_Temp_Insight)
        {
            logout("Temp","CoolBegin_Temp_Insight is less than HeatingBegin_Temp_Insight",6);
            return;
        }
        //白天只能加热 如果内部温度低于m_HeatingBeginTemp_Insight 则加热 否则停止加热
        //第一步 获取内部最小温度
        float mininsighttemp=GetMin_of_Vector(INSIGHT_TEMPERATURE);
        //第二步 与m_HeatingBeginTemp_Insight比较
        if (mininsighttemp<m_HeatingBegin_Temp_Insight)
        {
            m_TG_Manager->Heating(true);
            logout("Temp","current min insight temp is "+QString::number(mininsighttemp),6);
        }
        else
        {
            m_TG_Manager->Stop();
            logout("Temp","current min insight temp is "+QString::number(mininsighttemp),6);
        }


    }
    else //夜晚
    {
        //夜间只降温 且只要外部温度大于内部温度即降温
        //第一步 获取内部最大温度
        float maxinsighttemp=GetMax_of_Vector(INSIGHT_TEMPERATURE);
        //第二步 获取外部最小温度
        float minoutsighttemp=GetMin_of_Vector(OUTSIGHT_TEMPERATURE);
        // 如果外部温度小于内部温度
        if (maxinsighttemp>minoutsighttemp)
        {
            m_TG_Manager->Cooling(true);
            logout("Temp","current max insight temp is "+QString::number(maxinsighttemp),6);
        }
        else
        {
            m_TG_Manager->Stop();
            logout("Temp","current max insight temp is "+QString::number(maxinsighttemp),6);
        }
    }



    return;


    float tempreture=m_TemperaTureWoker->m_Tempreaturegroups[m_target_index].tempera[m_target_indey];
    //printf("current tempreture is %f\n",tempreture);
    logout("Temp","current tempreture is "+QString::number(tempreture),6);
   // qDebug()<< "current tempreture is " << tempreture;
    if (tempreture>M_Targert_Max_Tempreature)
    {
        m_TG_Manager->Cooling(true);
    }
    else if (tempreture<M_Targert_Min_Tempreature)
    {
        m_TG_Manager->Heating(true);
    }
    else
    {
        m_TG_Manager->Stop();
    }


}

bool TemperatureRegulator::looptask() {
    g_tempretureRegulator->loopsample();
}


