#include "common.h"
#include "self_devicecontrol.h"
#include "modules_common.h"
#include "app_device_common.h"
#include "drivers_common.h"


static ThreadPool_t *g_self_devicecontrol_task_t;//自控任务线程函数

static bool g_self_device_control_switch_index=false;//自控开关。是否打开或者关闭

static int g_self_control_interval=0;

static int g_self_control_time_count=0;
static pthread_mutex_t g_self_control_time_count_mutex = PTHREAD_MUTEX_INITIALIZER;

static devicecontroltask_t *g_self_device_control_date=NULL;//设备自控全局数据指针
static pthread_mutex_t g_self_device_control_date_mutex = PTHREAD_MUTEX_INITIALIZER;

static device_automatic_date_t g_automatic_date_t[DEVICE_WALK_SIGN_MAX]={0};

/*
* @brief 释放内存
*/
void free_device_tasks_memory() { 
    if(g_self_device_control_date!=NULL){
         pthread_mutex_lock(&g_self_device_control_date_mutex);
         free(g_self_device_control_date);
         g_self_device_control_date=NULL;
         my_zlog_info("free g_self_device_control_date");
         pthread_mutex_unlock(&g_self_device_control_date_mutex);
    } else return;  
   
}

/*
* @brief 分配内存封装函数
*/
void malloc_device_tasks_memory() {
    pthread_mutex_lock(&g_self_device_control_date_mutex);
    if(g_self_device_control_date==NULL){
        g_self_device_control_date=(devicecontroltask_t*)malloc(sizeof(devicecontroltask_t));
        my_zlog_info("malloc g_self_device_control_date");
    }
   pthread_mutex_unlock(&g_self_device_control_date_mutex);
}


/*
* @brief 自控线程中的计时函数接口,每20ms加一次
* @param[in] self_control_time_count，计时次数
*/
void set_self_control_time_countfuntion(){
    pthread_mutex_lock(&g_self_control_time_count_mutex);
    g_self_control_time_count++;
    if(g_self_control_time_count>30000) g_self_control_time_count=30001;
    pthread_mutex_unlock(&g_self_control_time_count_mutex);
}


/*
* @brief 自控线程中的任务
*/
void self_device_control_task(){
    static int i=0;

    static unsigned char valt[3];

    int time_now = g_self_control_time_count*20;

    if(i>=g_self_device_control_date->id_run_count){
            
            if(g_self_control_interval<time_now){
               
                return;
            }
            i=0;
    }
    if(time_now > g_self_device_control_date->run_cool[i]&&
        time_now <= (g_self_device_control_date->run_cool[i]+g_self_device_control_date->timed_run[i]))
    {
        for(int j=0;j<g_automatic_date_t[g_self_device_control_date->id_run[i]].action_count;j++){

            valt[1]=g_automatic_date_t[g_self_device_control_date->id_run[i]].mode[j];
            valt[2]=g_automatic_date_t[g_self_device_control_date->id_run[i]].val[j];
        
            if(valt[2]>2) device_walk_control(g_device_type,valt);
            else if(valt[2]<=2) device_gpio_control(g_device_type,valt[1],valt[2]);
            my_zlog_debug("date:%d",g_automatic_date_t[g_self_device_control_date->id_run[i]].action_count);
            my_zlog_debug("mode:%d",g_automatic_date_t[g_self_device_control_date->id_run[i]].mode[j]);
            my_zlog_debug("val:%d",g_automatic_date_t[g_self_device_control_date->id_run[i]].val[j]);
        }

    }else if(time_now >
            (g_self_device_control_date->run_cool[i]+g_self_device_control_date->timed_run[i]))
    {
    
        device_stop(g_device_type);//停止

        pthread_mutex_lock(&g_self_control_time_count_mutex);
        g_self_control_time_count=0;//将计时重置
        pthread_mutex_unlock(&g_self_control_time_count_mutex); 
        i=i+1;
    }
  
}


/*
* @brief 自控线程
*/
void self_device_control_task_function(){
    my_zlog_info("自控线程池循环开始");
    static int s_status =0; 
    while(1){
        if(g_self_device_control_switch_index==true){
            self_device_control_task();
            s_status=1;
        }else if(g_self_device_control_switch_index==false){
            if(s_status==1) {
                device_stop(g_device_type);
                s_status=0;
            }
            delay_ms(100);
        }
    }
    my_zlog_info("自控线程池循环终止");
    return ;
}

/*
* @brief 开启自控线程
*/
void self_device_pthrpoll_task_init(){

	g_self_devicecontrol_task_t=thread_pool_init(1,1);
	thread_pool_add_task(g_self_devicecontrol_task_t, self_device_control_task_function, NULL);
	my_zlog_info("自控线程池打开");
}

/*
* @brief 自控的线程开启标识设置。
* @param[in]  当index为，true为开，false为关
*/
void set_self_control_index(bool index){    
    g_self_device_control_switch_index =index;
}

/*
* @brief 获取自控的线程开启标识。
*/
bool get_self_control_index(){
    return g_self_device_control_switch_index;
}

/*
* @brief 销毁自控的线程
*/
void self_control_thread_close(){
    if(get_self_control_index()==true){
        my_zlog_info("Destroy the thread of the automatic control device");
	    thread_pool_destroy(g_self_devicecontrol_task_t);
    }
    my_zlog_info("The thread of the automatic control device is not opened");
}

/*
* @brief 返回MQTT自控打开或者关闭的函数 
*/
void send_self_contorl_mqtt(){
    // 创建根对象
    cJSON *root = cJSON_CreateObject();
    
    // 创建head对象
    cJSON *head = cJSON_CreateObject();
    cJSON_AddNumberToObject(head, "message_type", 3018);
    cJSON_AddItemToObject(root, "head", head);
    
    // 创建body对象
    cJSON *body = cJSON_CreateObject();
    cJSON_AddStringToObject(body, "cmd", "device_mycontrol");
    cJSON_AddNumberToObject(body, "switch_reply_status", get_self_control_index());
    cJSON_AddItemToObject(root, "body", body);
    
    // 将cJSON对象转换为字符串
    char *json_str = cJSON_PrintUnformatted(root);

    my_zlog_info("%s",json_str);

    for(int i=0;i<g_mqtt_cam_config_t->mqtt_count;i++){
        mosquitto_publish(g_clients_t[i].mosq, NULL, mqtt_topic_pure_number(), strlen(json_str), json_str, 0, false); 
    } 

    cJSON_Delete(root);  // 释放 cJSON 对象
}

/*
* @brief MQTT发送自控的相关的动作控制消息的函数，找后端要动作组合
*/
void send_self_contorl_date_mqtt(){
        // 创建根对象
    cJSON *root = cJSON_CreateObject();
    
    // 创建head对象
    cJSON *head = cJSON_CreateObject();
    cJSON_AddNumberToObject(head, "message_type", 3019);
    cJSON_AddItemToObject(root, "head", head);
    
    // 创建body对象
    cJSON *body = cJSON_CreateObject();
    cJSON_AddStringToObject(body, "cmd", "device_control_demand_date");
    cJSON_AddNumberToObject(body, "status", 1);
    cJSON_AddItemToObject(root, "body", body);
    
    // 将cJSON对象转换为字符串
    char *json_str = cJSON_PrintUnformatted(root);

    my_zlog_info("%s",json_str);

    for(int i=0;i<g_mqtt_cam_config_t->mqtt_count;i++){
        mosquitto_publish(g_clients_t[i].mosq, NULL, mqtt_topic_pure_number(), strlen(json_str), json_str, 0, false); 
    } 

    cJSON_Delete(root);  // 释放 cJSON 对象
}


/*
* @brief MQTT接收自控消息的函数 
*/
void receive_self_contorl_mqtt(cJSON *body){

    if (!body) {
        my_zlog_error("JSON error!");
        return;
    }

    cJSON *switch_status = cJSON_GetObjectItem(body, "switch_status");
    static int s_switch_status = 0;
    static bool s_thread_index=0;
    s_switch_status=switch_status->valueint;
    if(s_switch_status == DEVICE_SELF_CONTROL_OPEN){
       if(s_thread_index==0) {
        self_device_pthrpoll_task_init();
        send_self_contorl_date_mqtt();//找后端要动作组合
       }
       g_self_control_time_count=0;
       g_self_device_control_switch_index =true;
       s_thread_index=1;
    }else if(s_switch_status == DEVICE_SELF_CONTROL_CLOSE) {
       g_self_device_control_switch_index =false;
       free_device_tasks_memory();
       send_self_contorl_mqtt();
       return ;
    }

    cJSON *interval=cJSON_GetObjectItem(body, "interval");
    g_self_control_interval=interval->valueint;

    malloc_device_tasks_memory();//分配内存

    // 2️ id_run 数组
    cJSON *id_run = cJSON_GetObjectItem(body, "id_run");
    g_self_device_control_date->id_run_count = 0;
    if (cJSON_IsArray(id_run)) {
        int size = cJSON_GetArraySize(id_run);
        for (int i = 0; i < size && i < DEVICE_WALK_SIGN_MAX; i++) {
            cJSON *item = cJSON_GetArrayItem(id_run, i);
            g_self_device_control_date->id_run[i] = item->valueint;
            g_self_device_control_date->id_run_count++;
        }
    }

     // 3 run_cool 数组
    cJSON *run_cool = cJSON_GetObjectItem(body, "run_cool");
    //g_self_device_control_date->id_run_count = 0;
    if (cJSON_IsArray(run_cool)) {
        int size = cJSON_GetArraySize(run_cool);
        for (int i = 0; i < size&& i < DEVICE_WALK_SIGN_MAX ; i++) {
            cJSON *item = cJSON_GetArrayItem(run_cool, i);
            g_self_device_control_date->run_cool[i] = item->valueint;
            //g_self_device_control_date->id_run_count++;
        }
    }

      // 4 timed_run 数组
    cJSON *timed_run = cJSON_GetObjectItem(body, "timed_run");
    //g_self_device_control_date->id_run_count = 0;
    if (cJSON_IsArray(timed_run)) {
        int size = cJSON_GetArraySize(timed_run);
        for (int i = 0; i < size && i < DEVICE_WALK_SIGN_MAX ; i++) {
            cJSON *item = cJSON_GetArrayItem(timed_run, i);
            g_self_device_control_date->timed_run[i] = item->valueint;
            //g_self_device_control_date->id_run_count++;
        }
    }

    send_self_contorl_mqtt();

    my_zlog_info("count:%d",g_self_device_control_date->id_run_count);

    return;
}

/*
* @brief MQTT接收自控的相关的动作控制消息的函数，接收后端相应动作组合
*/
void receive_self_contorl_date_mqtt(cJSON *body){
    if (!body) {
        my_zlog_error("JSON error!");
        return;
    }

    cJSON *switch_status = cJSON_GetObjectItem(body, "switch_status");
    static int s_switch_status = 0;
    s_switch_status=switch_status->valueint;

    cJSON *action_id = cJSON_GetObjectItem(body, "action_id");
    static int s_action_id = 0;
    s_action_id=action_id->valueint;

    if(s_switch_status == 1){
            // 2️ id_run 数组
        cJSON *action_combination = cJSON_GetObjectItem(body, "action_combination");
        if (cJSON_IsArray(action_combination)) {
            int size = cJSON_GetArraySize(action_combination);
            for (int i = 0; i < size && i < DEVICE_WALK_SIGN_MAX; i++) {
                cJSON *item = cJSON_GetArrayItem(action_combination, i);

                g_automatic_date_t[s_action_id].mode[i]=item->valueint;
                
            }
        }

        cJSON *action_speed = cJSON_GetObjectItem(body, "action_speed");
        if (cJSON_IsArray(action_speed)) {
            int size = cJSON_GetArraySize(action_speed);
            for (int i = 0; i < size && i < DEVICE_WALK_SIGN_MAX; i++) {
                cJSON *item = cJSON_GetArrayItem(action_speed, i);

                g_automatic_date_t[s_action_id].val[i]=item->valueint;
                g_automatic_date_t[s_action_id].action_count++;
                
            }
        }
        
    }else if(s_switch_status == 0){
        memset(g_automatic_date_t[s_action_id].mode, 0, sizeof(g_automatic_date_t[s_action_id].mode));
        memset(g_automatic_date_t[s_action_id].val, 0, sizeof(g_automatic_date_t[s_action_id].val));
    }

    my_zlog_info("action_count:%d",g_automatic_date_t[s_action_id].action_count);

    return;

}
