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

#define GPIO_ID_THREAD_COUNT 3
#define GPIO_ID_SHOT_ONLYCOOL_COUNT 4 //仅需要打开射击冷却的设备数量

int gpio_device_id[GPIO_ID_THREAD_COUNT]={DEVICE_TANK0202,DEVICE_TANK0203,DEVICE_TANK0204};//需要打开线程池设备号
int gpio_device_cool_id[GPIO_ID_SHOT_ONLYCOOL_COUNT]={DEVICE_TANK0202,DEVICE_TANK0203,DEVICE_TANK0204,DEVICE_TANK0206};//仅需要打开射击冷却的设备号

const gpiocontrol_t *gpio_control_config_t = NULL ;//gpio结构体标识

ThreadPool_t *g_pool_device_gpio_control_t;//gpio限位线程池标识，只在特地设备中打开

void public_pin_value(int pin,int value);
void car0102_pin_value(int pin,int value);
void car0103_pin_value(int pin,int value);
void car0104_pin_value(int pin,int value);

void public_pwm_value(int pin ,int value);
void tank0202_pwm_value(int pin,int value);
void tank0203_pwm_value(int pin,int value);
void tank0204_pwm_value(int pin,int value);
void tank0206_pwm_value(int pin,int value);
void ship0301_pwm_value(int pin,int value); 
void dog0501_pwm_value(int pin,int value);

TankFireControl g_device_shot_t;   // 真正的结构体变量

/**
 * @brief 初始化坦克射击控制器
 * @param this 控制器指针
 * @param shot_interval_ms 冷却时间（毫秒）
 * @param shot_duration_ms 射击持续时间（毫秒）
 */
void device_shot_fire_init(TankFireControl* this) {
    if(g_device_type==DEVICE_TANK0206){
        this->last_shot_end_time = 0;
        this->shooting_start_time = 0;
        this->state = TANK_STATE_READY;
        this->shot_interval_ms = 1000;
        this->shot_duration_ms = 1000;
    }else{
        this->last_shot_end_time = 0;
        this->shooting_start_time = 0;
        this->state = TANK_STATE_READY;
        this->shot_interval_ms = 5000;
        this->shot_duration_ms = 1000;
    }
    
}

/*
**射击需要的相关设备冷却初始化
**对需要射击冷却的进行初始化
*/
int device_shot_cooling_init(){
    for(int i=0;i<GPIO_ID_SHOT_ONLYCOOL_COUNT;i++){
        if(g_device_type==gpio_device_cool_id[i]){
            my_zlog_info("using %d shot init",g_device_type);
            device_shot_fire_init(&g_device_shot_t);
            return 0; 
        }
    }
    return -1;
}

/**
 * @brief 检查射击状态
 * @param this 控制器指针
 * @return 0=允许射击, -1=禁止射击（冷却中或射击中）
 */
int device_fire_check(TankFireControl* this) {
    uint64_t current_time = get_current_time_millis(); // 假设已实现此函数

    if (current_time - this->last_shot_end_time >= this->shot_interval_ms){
                this->state = TANK_STATE_READY;
                my_zlog_info("coolend");
                return 0; // 冷却完成
    }

    switch (this->state) {
        case TANK_STATE_READY:
            if (current_time - this->last_shot_end_time < this->shot_interval_ms) {
                return -1; // 仍在冷却
            }
            my_zlog_info("shot start");
            // 开始新射击
            this->shooting_start_time = current_time;
            this->state = TANK_STATE_SHOOTING;
            return 0;

        case TANK_STATE_SHOOTING:
            if (current_time - this->shooting_start_time > this->shot_duration_ms) {
                // 射击结束，进入冷却
                my_zlog_info("shotend，cooling");
                this->last_shot_end_time = current_time;
                this->state = TANK_STATE_COOLDOWN;
                g_tank_shot_index_cool=0;
                return -1;
            }
            my_zlog_info("shot continue");
            return 0; // 继续射击

        case TANK_STATE_COOLDOWN:
            if (current_time - this->last_shot_end_time >= this->shot_interval_ms) {
                this->state = TANK_STATE_READY;
                my_zlog_info("coolend");
                return 0; // 冷却完成
            }
            return -1; // 仍在冷却
    }
    return -1;
}

/*
* @brief 设备加上冷却射击切换
*/
int device_shoting_check(int pin,int val){
    if(device_fire_check(&g_device_shot_t)!=0){
        softPwmWrite(pin, 0);
    }else if(device_fire_check(&g_device_shot_t)==0){
        softPwmWrite(pin, val);
    }
}

/*
* @brief 坦克限位线程函数*/
void tank_angle_limit_function(void *arg_gpio){
    static int limit_log_count=0;
     if (arg_gpio != NULL) {
        free(arg_gpio);
    }
    my_zlog_info("limit task started.");
    while(1){
        int limit_status = angle_limit();
        if(limit_status==1) {
            device_gpio_control(g_device_type,5,0);
            my_zlog_info("lift limit stop");
        }
        else if(limit_status==2) {
            device_gpio_control(g_device_type,7,0);
            my_zlog_info("right limit stop");
        }
        else if(limit_status==0) {
            delay_ms(5);
            limit_log_count++;
            if(limit_log_count>=400){
                my_zlog_info("limit stop");
                limit_log_count=0;
            }
            
        }
    }
    free(arg_gpio);
}

/*角度限位线程池初始化*/
void device_gpio_control_threadpoll_init(){
    int *arg_gpio = malloc(sizeof(int));
    my_zlog_info("device_gpio_control_threadpoll_init start");
    *arg_gpio = 2;
    g_pool_device_gpio_control_t = thread_pool_init(1,1);
    thread_pool_add_task(g_pool_device_gpio_control_t, tank_angle_limit_function, arg_gpio);
}

/*设备拉低引脚结构体数组*/
const gpiocontrol_t gpio_configs[] = {
    {
        .device_id = DEVICE_CAR0101,
        .category_id=LAND_CAR,
        .device_pin_value =public_pin_value,
        .device_pwm_value =public_pwm_value
    },
    {
        .device_id = DEVICE_CAR0102,
        .category_id=LAND_CAR,
        .device_pin_value =car0102_pin_value,
        .device_pwm_value =public_pwm_value
    },
    {
        .device_id = DEVICE_CAR0103,
        .category_id=LAND_CAR,
        .device_pin_value =car0103_pin_value,
        .device_pwm_value =public_pwm_value
    },
    {
        .device_id = DEVICE_CAR0104,
        .category_id=LAND_CAR,
        .device_pin_value =car0104_pin_value,
        .device_pwm_value =public_pwm_value
    },
    {
        .device_id = DEVICE_TANK0202,
        .category_id=MARINE_TANK,
        .device_pin_value =public_pin_value,
        .device_pwm_value =tank0202_pwm_value,
        .device_gpio_pthread_create=device_gpio_control_threadpoll_init
    },
    {
        .device_id = DEVICE_TANK0203,
        .category_id=MARINE_TANK,
        .device_pin_value =public_pin_value,
        .device_pwm_value =tank0203_pwm_value,
        .device_gpio_pthread_create=device_gpio_control_threadpoll_init
    },
    {
        .device_id = DEVICE_TANK0204,
        .category_id=MARINE_TANK,
        .device_pin_value =public_pin_value,
        .device_pwm_value =tank0204_pwm_value,
        .device_gpio_pthread_create=device_gpio_control_threadpoll_init
    },
    {
        .device_id = DEVICE_TANK0206,
        .category_id=WATER_TANK,
        .device_pin_value =public_pin_value,
        .device_pwm_value =tank0206_pwm_value
    },
    {
        .device_id = DEVICE_SHIP0301,
        .category_id=WATER_SHIP,
        .device_pin_value =public_pin_value,
        .device_pwm_value =ship0301_pwm_value
    },
    {
        .device_id = DEVICE_PAO_PTZ0401,
        .category_id=0,
        .device_pin_value =public_pin_value,
        .device_pwm_value =public_pwm_value
    },
    {
        .device_id = DEVICE_ROBOT_DOG0501,
        .category_id=0,
        .device_pin_value =public_pin_value,
        .device_pwm_value =dog0501_pwm_value
    },
    // 结束标记
    { .device_id = -1 }
};

/*
设备控制代码
*/
void device_gpio_control(int device_id,int pin,int val) {

    if (!gpio_control_config_t || gpio_control_config_t->device_id != device_id) {
        // 查找设备配置
        for(int i = 0; gpio_configs[i].device_id != -1; i++) {
            if(gpio_configs[i].device_id == device_id) {
                gpio_control_config_t = &gpio_configs[i];
                break;
            }
        }
        for(int i=0;i<GPIO_ID_THREAD_COUNT;i++ ){
            if(gpio_control_config_t && device_id == gpio_device_id[i]){
                my_zlog_info("线程函数:%d", device_id);
                gpio_control_config_t->device_gpio_pthread_create(); //创建线程，线程关闭在tank.common.h中何tank需要的其他线程关闭
            }
        }
    }
    
    if(!gpio_control_config_t) {
        my_zlog_error("Error: Device gpio stop ID %d not found!", device_id);
        return;
    }

    gpio_control_config_t->device_pin_value(pin,val);
    gpio_control_config_t->device_pwm_value(pin,val);         
}

void public_pin_value(int pin,int value) {	//引脚控制
	for(int i = 0 ; i <= g_gpiocount ; i++) {
        if(pin == g_gpiowpi[i]) {
            break;
        }if(i == g_gpiocount) {
            return ;
        }   
    }
    if(value==1) {
		digitalWrite(pin, HIGH);
		my_zlog_info("pin:%d,%d",pin,HIGH);
	}else if(value==0) {
		digitalWrite(pin, LOW);
		my_zlog_info("pin:%d,%d",pin,LOW);
	}
	
}

/*
* @brief 小车pin控制
*/
void car0102_pin_value(int pin,int value) {	//引脚控制
	for(int i = 0 ; i <= g_gpiocount ; i++) {
        if(pin == g_gpiowpi[i]) {
            break;
        }if(i == g_gpiocount) {
            return ;
        }   
    }
    if(value==1) {
		digitalWrite(pin, HIGH);
        if(pin==26){
            static int i=0;
            i++;
            if(i>10) {
                my_zlog_info("pin:%d,%d",pin,HIGH);
                i=0;
            }
            return;
        }
		my_zlog_info("pin:%d,%d",pin,HIGH);
	}else if(value==0) {
		digitalWrite(pin, LOW);
        if(pin==26){
            static int i=0;
            i++;
            if(i>10) {
                my_zlog_info("pin:%d,%d",pin,HIGH);
                i=0;
            }
            return;
        }
		my_zlog_info("pin:%d,%d",pin,LOW);
	}
	
}

/*
* 挖斗检测函数，此为反馈要快，所以加入到计时线程中
*/
void device_fast_read(){
    if(g_device_type==DEVICE_CAR0103) {
        if(digitalRead(18)==LOW) {
            digitalWrite(7, LOW);
        return ;
        }
    }else {
        return ;
    }
}

/*
* 读取相应的引脚做出相应的反馈
*/
int car0103_pin_read(int pin){
    if(digitalRead(20)==LOW&& pin==24){
        digitalWrite(24, LOW);
        return 1;
    }else if(digitalRead(11)==LOW&& pin==26) {
        digitalWrite(26, LOW);
        digitalWrite(27, LOW);
        return 1;
    }
     if(digitalRead(12)==LOW&& pin==9){
        digitalWrite(9, LOW);
        return 1;
    }else if(digitalRead(14)==LOW&& pin==10) {
        digitalWrite(10, LOW);
        return 1;
    }
     if(digitalRead(17)==LOW&& pin==5){
        digitalWrite(5, LOW);
        return 1;
    }else if(digitalRead(18)==LOW&& pin==7) {
        digitalWrite(7, LOW);
        return 1;
    }
    return 0;
}



/*挖机pin控制*/
void car0103_pin_value(int pin,int value){
    if(car0103_pin_read(pin)==1) return ;

    if(pin == 26 && value==1) {
        public_pin_value(27,1);
        public_pin_value(pin,value);
    }else if(pin == 26 && value==0){
        public_pin_value(27,0);
        public_pin_value(pin,value);
    }else if(pin == 253 && value==1){
        public_pin_value(27,0);
        public_pin_value(26,1);
        public_pin_value(24,1);
    }else if(pin == 254 && value==1){
        public_pin_value(27,1);
        public_pin_value(26,0);
        public_pin_value(24,0);
    }else if((pin == 254||pin == 253) && value==0){
        public_pin_value(27,0);
        public_pin_value(26,0);
        public_pin_value(24,0);
    }else {
        public_pin_value(pin,value);
    }
}

/*推土机pin控制*/
void car0104_pin_value(int pin,int value){
    if(pin==24){
        public_pin_value(26,value);
    }else if(pin==26){
        public_pin_value(24,value);
    }else public_pin_value(pin,value);
}

void public_pwm_value(int pin ,int value){
        for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
            if(pin == g_gpioPwm[i]) {
                break;
            }
            if(i == g_gpio_softpwmcount) {
                return ;
            }
    }
     
    int shot_speed = (int)(g_shot_speed_value*100);
    if(value==1) {
		
		if(pin == 27){
                softPwmWrite(pin, shot_speed);
                my_zlog_info("pwm:%d,%d",pin,shot_speed);
        } else {
                softPwmWrite(pin, shot_speed);
                 my_zlog_info("pwm:%d,%d",pin,shot_speed);
        }
        
	}else if(value==0) {
		softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
    my_zlog_info("public pwm");

}

void tank0202_pwm_value(int pin,int value) {	//软件陪我们控制调速
    for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    
    if(value==1) {
		if(pin == 27){
            device_shoting_check(27,30);   
        } else {
            softPwmWrite(pin, 30);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
		softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
     my_zlog_info("tank0202 pwm");
}

void tank0203_pwm_value(int pin,int value) {	//软件陪我们控制调速
    for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    if(value==1) {
		
		if(pin == 27){
            device_shoting_check(27,30); 
        } else {
            softPwmWrite(pin, 30);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
		softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
    my_zlog_info("tank0203 pwm");
}

void tank0204_pwm_value(int pin,int value){
        for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    if(value==1) {
		
		if(pin == 27){
          device_shoting_check(27,30); 
        }else if(pin == 5) {
            softPwmWrite(7, 25);
            my_zlog_info("pwm:7,1");
        }else if(pin == 7) {
            softPwmWrite(5, 25);
            my_zlog_info("pwm:5,1");
        }else {
            softPwmWrite(pin, 60);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
         if(pin == 5) {
            softPwmWrite(7, 0);
            my_zlog_info("pwm:7,0");
        }else if(pin == 7) {
            softPwmWrite(5, 0);
            my_zlog_info("pwm:5,0",pin);
        }else{
            softPwmWrite(pin, 0);
            my_zlog_info("pwm:%d,0",pin);
        }
	}
    my_zlog_info("tank0204 pwm");
}

void tank0206_pwm_value(int pin,int value) {	//软件陪我们控制调速
    for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    
    if(value==1) {
		if(pin == 27){
            device_shoting_check(26, 35);
        } else {
            softPwmWrite(pin, 35);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
        if(pin == 27) softPwmWrite(26, 0);
		softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
     my_zlog_info("tank0206 pwm");
}

void ship0301_pwm_value(int pin,int value) {	//软件陪我们控制调速
    for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    
    if(value==1) {
		if(pin == 27){
            softPwmWrite(26, 35);
        } else {
            softPwmWrite(pin, 35);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
        if(pin == 27) softPwmWrite(26, 0);
		softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
     my_zlog_info("tank0301 pwm");
}


void dog0501_pwm_value(int pin,int value) {	//软件陪我们控制调速
    for(int i = 0 ; i <= g_gpio_softpwmcount ; i++) {
        if(pin == g_gpioPwm[i]) {
            break;
        }
        if(i == g_gpio_softpwmcount) {
            return ;
        }
    }
    
    if(value==1) {
		if(pin == 27){
            softPwmWrite(27, 40);
            softPwmWrite(7, 100);
        } else {
            softPwmWrite(pin, 35);
            my_zlog_info("pwm:%d",pin);
        }
        
	}else if(value==0) {
        if(pin==27){
            softPwmWrite(27, 0);
            softPwmWrite(7, 0);
        }else  softPwmWrite(pin, 0);
		my_zlog_info("pwm:%d,0",pin);
	}
     my_zlog_info("dog0501 pwm");
}


