#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 5 //仅需要打开射击冷却的设备数量

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

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 tank0207_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 if(g_device_type==DEVICE_TANK0207){
        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 if(g_device_type==DEVICE_TANK0204){
        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 = 1500;
        tankshot_detection_backcount(&this->shot_interval_ms,0);
    }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();

    // -----------------------------------------------------------
    // 第一步：检查冷却是否结束 (COOLDOWN -> READY)
    // -----------------------------------------------------------
    if (this->state == TANK_STATE_COOLDOWN) {
        if (current_time - this->last_shot_end_time >= this->shot_interval_ms) {
            this->state = TANK_STATE_READY;
            my_zlog_info("coolend -> ready");
            // 注意：这里不要 return，让代码继续往下执行，
            // 这样如果冷却刚结束，马上就能在下面进入射击逻辑
        } else {
            // 还在冷却中，直接返回
            return -1;
        }
    }

    // -----------------------------------------------------------
    // 第二步：检查是否可以开始新射击 (READY -> SHOOTING)
    // -----------------------------------------------------------
    // 逻辑流转到这里有两种情况：
    // 1. 本来就是 READY 状态
    // 2. 刚刚从 COOLDOWN 变成了 READY
    if (this->state == TANK_STATE_READY) {
        // 双重检查：确保时间间隔满足（防止异常状态跳变）
        if (current_time - this->last_shot_end_time >= this->shot_interval_ms) {
            my_zlog_info("shot start");
            this->shooting_start_time = current_time;
            this->state = TANK_STATE_SHOOTING;
            // 开始射击了，这里不需要立即 return，
            // 可以选择继续执行由 SHOOTING 块处理（如果你想立即检查是否瞬间射完），
            // 但通常射击需要持续一段时间，直接返回 0 表示正在射击即可。
            return 0; 
        }
        // 如果状态是READY但时间不够（理论上不该发生），修正状态或等待
        return -1; 
    }

    // -----------------------------------------------------------
    // 第三步：处理射击持续过程 (SHOOTING -> COOLDOWN)
    // -----------------------------------------------------------
    if (this->state == TANK_STATE_SHOOTING) {
        if (current_time - this->shooting_start_time > this->shot_duration_ms) {
            my_zlog_info("shot end -> cooling");
            
            // 【优化】计算理论结束时间，消除 100ms 轮询带来的时间漂移
            // 如果不在意精度，依然可以用 current_time
            // this->last_shot_end_time = this->shooting_start_time + this->shot_duration_ms; 
            this->last_shot_end_time = current_time; 

            this->state = TANK_STATE_COOLDOWN;

            set_tank_shot_index_cool(0);//当为0坦克才能进入发炮完后退时间重置
            return -1; // 射击刚刚结束
        }
        
        my_zlog_info("shot continue ...");
        return 0; // 正在射击中
    }

    return -1;
}

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

#define LIMIT_LIFT  1
#define LIMIT_RIGHT 2
static int limit_status=0;
/*
* @brief 坦克限位线程函数*/
void tank_angle_limit_function(){
    static int limit_log_count=0;
    my_zlog_info("limit task started.");
    while(1){
        limit_status = angle_limit();
        if(limit_status==LIMIT_LIFT) {
            device_gpio_control(g_device_type,5,0);
            if(limit_log_count>100){
                my_zlog_info("right limit");
                limit_log_count=0;
            }
        }
        else if(limit_status==LIMIT_RIGHT) {
            device_gpio_control(g_device_type,7,0);
            if(limit_log_count>100){
                my_zlog_info("lift limit");
                limit_log_count=0;
            }
        }

        else if(limit_status==0) {
            limit_log_count++;
            if(limit_log_count>100){
                my_zlog_info("limit stop");
                limit_log_count=0;
            }
            delay_ms(5);
        }
         
    
    }
}

/*角度限位线程池初始化*/
void device_gpio_control_threadpoll_init(){
    my_zlog_info("device_gpio_control_threadpoll_init start");
    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, NULL);
}

/*设备拉低引脚结构体数组*/
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_TANK0207,
        .category_id=WATER_TANK,
        .device_pin_value =public_pin_value,
        .device_pwm_value =tank0207_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");

}

/*引脚复用检查，26引脚检查，只有使用的需要*/
int devicegpio_pwmreuse(int pin,int value,int val){
    if(pin==26&&value==1){
        tankshot_detection_backcount(NULL,4);
        softPwmWrite(27, val);
    }
    if(pin==26&&value==0){
        softPwmWrite(27, val);
    }
} 

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);
            devicegpio_pwmreuse(pin,value,30);
            my_zlog_info("pwm:%d",pin);
        }
        if(limit_status==LIMIT_LIFT) {
            softPwmWrite(5, 0);
            //device_gpio_control(g_device_type,5,0);
            my_zlog_info("lift limit stop");
        }else if(limit_status==LIMIT_RIGHT) {
            softPwmWrite(7, 0);
            //device_gpio_control(g_device_type,7,0);
            my_zlog_info("right limit stop");
        }
        
	}else if(value==0) {
		softPwmWrite(pin, 0);
        devicegpio_pwmreuse(pin,value,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);
            devicegpio_pwmreuse(pin,value,30);
            my_zlog_info("pwm:%d",pin);
        }
        if(limit_status==LIMIT_LIFT) {
            softPwmWrite(5, 0);
            //device_gpio_control(g_device_type,5,0);
            my_zlog_info("lift limit stop");
        }else if(limit_status==LIMIT_RIGHT) {
            softPwmWrite(7, 0);
            //device_gpio_control(g_device_type,7,0);
            my_zlog_info("right limit stop");
        }
        
        
	}else if(value==0) {
		softPwmWrite(pin, 0);
        devicegpio_pwmreuse(pin,value,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,100);
           if(getshot_detection_index()==true){
            softPwmWrite(27, 100);
            setshot_detection_index(false);
            tankshot_detection_backcount(NULL,3);
            set_backshotstatus(true);
            my_zlog_info("冷却完成，射击开始");
           }
           //set_tank_shot_index_cool(0);
        }else if(pin == 5) {
            softPwmWrite(7, 35);
            my_zlog_info("pwm:7,1");
        }else if(pin == 7) {
            softPwmWrite(5, 35);
            my_zlog_info("pwm:5,1");
        }else {
            if(pin==26&&get_backshotstatus()!=true) {
                devicegpio_pwmreuse(pin,value,60);
                softPwmWrite(pin, 60);
            }
            if(pin!=26)softPwmWrite(pin, 60);
            my_zlog_info("pwm:%d",pin);
        }

        if(limit_status==LIMIT_LIFT) {
            softPwmWrite(7, 0);
            //device_gpio_control(g_device_type,5,0);
            my_zlog_info("lift limit stop");
        }else if(limit_status==LIMIT_RIGHT) {
            softPwmWrite(5, 0);
            //device_gpio_control(g_device_type,7,0);
            my_zlog_info("right limit stop");
        }
        
	}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{
            if(pin!=27) {
                if(pin==26&&get_backshotstatus()!=true){
                    softPwmWrite(pin, 0);
                    devicegpio_pwmreuse(pin,value,0);
                }
            if(pin!=26)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 tank0207_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, 100);
        } 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");
}


