#include <ti_msp_dl_config.h>
#include <FreeRTOS.h>
#include <task.h>

#include <Print.h>
#include <Encoder.h>
#include <Imu.h>
#include <Motor.h>
#include <TrackerMpu.h>
#include <TrackerGpio.h>
#include <2025_include_user/Beep.h>
#include <Host.h>
#include <Key.h>
#include <Led.h>
#include <Servo.h>
#include <Stepmotor.h>
#include <Oled.hpp>
#include <OledMenuDriver.h>
#include <OledMenuPaint.h>
#include <TrackerGpio.h>
#include <TrackerGpio.h>


/************ 外部中断测试部分 ************/

extern "C" void GROUP1_IRQHandler() {
    //读取Group1的中断寄存器并清除中断标志位
    switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) {
        //检查是否是KEY的GPIOB端口中断，注意是INT_IIDX，不是PIN_22_IIDX
        case Key_GPIOA_INT_IIDX:
        case GPIO_MULTIPLE_GPIOB_INT_IIDX: {
            const uint32_t statusA = DL_GPIO_getPendingInterrupt(GPIOA);
            const uint32_t statusB = DL_GPIO_getPendingInterrupt(GPIOB);
            // print("%d\n", statusA);
            // print("%d\n", statusB);
            if (statusA == KEY1_PIN_ID + 1) {
                Key::keys[KEY1].state = 1;
            } else if (statusB == KEY2_PIN_ID + 1) {
                Key::keys[KEY2].state = 1;
            } else if (statusB == KEY3_PIN_ID + 1) {
                Key::keys[KEY3].state = 1;
            } else if (statusB == KEY4_PIN_ID + 1) {
                Key::keys[KEY4].state = 1;
            }
            // TrackerGpio::inject(Tracker_Track1_PIN, DL_GPIO_readPins(Tracker_Track1_PORT, Tracker_Track1_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track2_PIN, DL_GPIO_readPins(Tracker_Track2_PORT, Tracker_Track2_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track3_PIN, DL_GPIO_readPins(Tracker_Track3_PORT, Tracker_Track3_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track4_PIN, DL_GPIO_readPins(Tracker_Track4_PORT, Tracker_Track4_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track5_PIN, DL_GPIO_readPins(Tracker_Track5_PORT, Tracker_Track5_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track6_PIN, DL_GPIO_readPins(Tracker_Track6_PORT, Tracker_Track6_PIN) > 0);
            // TrackerGpio::inject(Tracker_Track7_PIN, DL_GPIO_readPins(Tracker_Track7_PORT, Tracker_Track7_PIN) > 0);
            DL_GPIO_clearInterruptStatus(GPIOA, statusA);
            DL_GPIO_clearInterruptStatus(GPIOB, statusB);
            break;
        }
        default:
            break;
    }
}

/************ FreeRtos 任务定义区 ************/

[[noreturn]] void vLedTask(void *pvParameters) {
    while (true) {
        Led::on(LED0);
        // DL_GPIO_setPins(Lights_PORT, Lights_Light_PIN);
        vTaskDelay(pdMS_TO_TICKS(500)); // 每500毫秒切换一次LED状态
        Led::off(LED0);
        // DL_GPIO_clearPins(Lights_PORT, Lights_Light_PIN);
        vTaskDelay(pdMS_TO_TICKS(500)); // 每500毫秒切换一次LE+D状态
    }
}

[[noreturn]] void vOledTask(void *pvParameters) {
    MenuDriver::init();
    MenuPaint::Init();
    while (true) {
        const int direction = (int) Host::get("Direction", 0);
        if (Key::getState(KEY1 || direction == 2)) {
            MenuPaint::ScrollUp();
        }
        if (Key::getState(KEY2) || direction == 8) {
            MenuPaint::ScrollDown();
        }
        if (Key::getState(KEY3) || direction == 4) {
            MenuPaint::Enter();
        }
        if (Key::getState(KEY4) || direction == 6) {
            MenuPaint::Exit();
        }

        MenuPaint::Paint();
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

[[noreturn]] void vTestTask(void *pvParameters) {
    while (true) {
        // print("Ctrl: %f\n", Host::get("Ctrl", 0.0));
        // print("x: %f\n", Host::get("x", 0.0));
        // print("y: %f\n", Host::get("y", 0.0));
        // Motor::setSpeed(3000, 3000);
        // TrackerGpio::Data data = TrackerGpio::getData(); // 每位数据：0 表示压线，1 表示空白
        // const char *d = data.data;
        //
        // print("Data:%d,%d,%d,%d,%d,%d,%d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6]);
        // vTaskDelay(pdMS_TO_TICKS(100));
    }
}

static uint8_t turn_limit = 0;
[[noreturn]] void vTrackerTask(void *pvParameters) {
    // 计算偏移量（简单加权）
    // 左侧为正，右侧为负
    constexpr float weights[7] = {-2.1, -1.5, -0.8, 0, 0.8, 1.5, 2.1};
    constexpr int base_speed = 4000; // 基础速度
    constexpr int adjust_speed = 2000; // 差速调整速度

    while (true) {
        if (turn_limit <= 0) {
            for (uint8_t i = 0; i < 5; i++) {
                if (MenuPaint::GetSwitchState(i) == 1) {
                    turn_limit = 4 * (i + 1) + 1;
                }
            }

            Motor::stop();
            vTaskDelay(pdMS_TO_TICKS(50));
            continue;
        }

        // 读取循迹传感器数据
        TrackerGpio::Data data = TrackerGpio::getData(); // 每位数据：0 表示压线，1 表示空白
        const char *d = data.data;

        float error = 0;
        int sum = 0;

        for (int i = 0; i < 7; ++i) {
            if (d[i] == 0) {
                // 压到线
                error += weights[i];
                sum++;
            }
        }

        if (sum == 0) {
            turn_limit--;
            if (turn_limit <= 0) {
                Motor::stop();
                vTaskDelay(pdMS_TO_TICKS(50));
                continue;
            }

            uint8_t is_speed = (MenuPaint::GetSwitchState(5) == 1) ? 1 : 0;
            uint8_t speed = is_speed ? 210 : 160;
            Motor::setLeftSpeed(0);
            Motor::setRightSpeed(speed * 10);
            while (true) {
                data = TrackerGpio::getData(); // 每位数据：0 表示压线，1 表示空白
                const char *inner_d = data.data;
                if (inner_d[3] == 0 || inner_d[2] == 0 || inner_d[1] == 0 || inner_d[0] == 0)
                    break;
                Motor::setLeftSpeed(0);
                Motor::setRightSpeed(speed * 10);
                vTaskDelay(pdMS_TO_TICKS(50));
            }
        } else {
            int left_speed = base_speed;
            int right_speed = base_speed;

            error = error / sum;
            // 差速控制，误差越大，左右轮速度差越大
            left_speed = (int) (base_speed - error * adjust_speed / 4);
            right_speed = (int) (base_speed + error * adjust_speed / 4);

            // 限制最大最小速度
            if (left_speed > 10000) left_speed = 10000;
            if (left_speed < -10000) left_speed = -10000;
            if (right_speed > 10000) right_speed = 10000;
            if (right_speed < -10000) right_speed = -10000;

            // 设置电机速度
            Motor::setLeftSpeed(left_speed);
            Motor::setRightSpeed(right_speed);

            vTaskDelay(pdMS_TO_TICKS(50));
        }
    }
}

[[noreturn]] void vStepMotorTask(void *pvParameters) {
    // // PID参数（根据实际调试再微调）
    //
    // const float integral_limit = 500.0f; // 积分限幅，避免积分快速累积
    // const float DEAD_ZONE = 10.0f; // 误差死区：误差在±5像素内不动作
    //
    // float integral = 0.0f;
    // float last_error = 0.0f;
    vTaskDelay(pdMS_TO_TICKS(500));

    while (true) {
        // DL_TimerG_setCaptureCompareValue(Servo_INST, (uint32_t)800, GPIO_Servo_C0_IDX);
        Servo::SetUpAngle(Host::getWithoutClean("angle", 87.0));
        // Servo::SetDownAngle(120);
        // // if (MenuPaint::GetSwitchState(5) == 0 || MenuPaint::GetSwitchState(6) == 0) {
        // //     vTaskDelay(pdMS_TO_TICKS(100));
        // //     continue;
        // // }
        //
        // const double Kp = Host::getWithoutClean("kp", 0.2);
        // const double Ki = Host::getWithoutClean("ki", 0.0005);
        // const double Kd = Host::getWithoutClean("kd", 0.006);
        // const double t_ = Host::posX; // 获取像素误差，范围0~240
        // const uint8_t direction = (t_ > 0) ? 1 : 0;
        // const double error = t_ > 0 ? t_ : -t_;
        //
        //
        // print("Kp: %f, Ki: %f, Kd: %f\n", Kp, Ki, Kd);
        //
        // // 死区处理
        // if (fabs(error) < DEAD_ZONE) {
        //     StepMotor::setPosition(0, 32, 0.0f, 0); // 停止动作
        //     integral = 0; // 死区内积分归零，避免积累
        //     // while (true) {
        //     //     // TODO 激光ON
        //     //     vTaskDelay(pdMS_TO_TICKS(1000));
        //     //     // TODO 激光OFF
        //     // }
        // } else {
        //     // 积分项累加 & 限幅
        //     integral += error;
        //     if (integral > integral_limit) integral = integral_limit;
        //     if (integral < -integral_limit) integral = -integral_limit;
        //
        //     // 微分项
        //     float derivative = error - last_error;
        //
        //     // PID输出
        //     float output = Kp * error + Ki * integral + Kd * derivative;
        //
        //     // 限制输出范围（0.3° ~ 2.0°）
        //     if (output < 0.3f) output = 0.3f;
        //     if (output > 4.0f) output = 4.0f;
        //
        //     // 控制步进电机
        //     StepMotor::setPosition(direction, 32, output, -10);
        //     // print("Motor: speed=%f, direction=%d\n", output, direction);
        //
        //     last_error = error; // 保存上次误差
        // }

        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

/***************** 主函数 ******************/

int main() {
    /*** SysConfig 初始化 ***/
    SYSCFG_DL_init();

    /*** 模块初始化 ***/
    Print_init();
    Encoder::init();
    // Imu::init();
    Motor::init();
    // TrackerMpu::init();
    // Beep::init();
    // Led::init();
    Host::init();
    Key::init();
    // StepMotor::init();

    /*** FreeRtos 任务初始化 ***/
    xTaskCreate(vLedTask, "TestLedTask", 32, nullptr, 1, nullptr);
    xTaskCreate(vOledTask, "vOledTask", 128, nullptr, 1, nullptr);
    // xTaskCreate(vTestTask, "vTestTask", 512, nullptr, 1, nullptr);
    xTaskCreate(vTrackerTask, "vTrackerTask", 256, nullptr, 1, nullptr);
    xTaskCreate(vStepMotorTask, "vStepMotorTask", 32, nullptr, 1, nullptr);


    /*** 启动 FreeRtos ***/
    vTaskStartScheduler();

    return 0;
}

/************ FreeRtos 错误处理部分 ************/

#ifdef __cplusplus
extern "C" {
#endif

void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    /* 栈溢出时的处理代码 */
    /* 例如，打印错误信息并重置系统 */

    /* 参数:
     * xTask - 发生栈溢出的任务句柄
     * pcTaskName - 发生栈溢出的任务名称
     */

    /* 通常在这里添加一些错误处理和系统恢复的代码 */
    while (1) {
        /* 可以在此处添加错误处理代码，如闪烁LED或输出调试信息 */
    }
}

/* 在全局范围内定义存储空间 */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];

/* 实现所需的函数 */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                   StackType_t **ppxIdleTaskStackBuffer,
                                   uint32_t *pulIdleTaskStackSize) {
    /* 传递静态分配的空闲任务数据结构的地址 */
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

    /* 传递静态分配的空闲任务堆栈的地址 */
    *ppxIdleTaskStackBuffer = uxIdleTaskStack;

    /* 传递堆栈大小 */
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}


/* 为定时器任务定义静态内存 */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize) {
    /* 传递静态分配的定时器任务数据结构的地址 */
    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

    /* 传递静态分配的定时器任务堆栈的地址 */
    *ppxTimerTaskStackBuffer = uxTimerTaskStack;

    /* 传递堆栈大小 */
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

#ifdef __cplusplus
}
#endif


// [[noreturn]] void vStepMotorTask(void *pvParameters) {
//     while (true) {
//         double speed = Host::posX;
//         uint8_t direction = 1;
//
//         if (Host::x_count <= 0) {
//             speed = 0.0;
//         } else {
//             Host::x_count--;
//             if (Host::x_count == 0) {
//                 Host::posX = 0.0;  // 用完后置零
//             }
//         }
//
//         direction = speed >= 0 ? 1 : 0;
//         speed = speed >= 0 ? speed : -speed;
//         StepMotor::setSpeed(direction, 32, float(speed));
//         print("Motor: speed=%f, direction=%d\n", speed, direction);
//
//         vTaskDelay(pdMS_TO_TICKS(70));
//     }
// }

// [[noreturn]] void vStepMotorTask(void *pvParameters) {
//     while (true) {
//         int error = (int) Host::posX;
//         uint8_t direction = error > 0;
//         if (error > 5 || error < -5) {
//             StepMotor::setPosition(direction, 32, 0.5, 10);
//         }
//
//         vTaskDelay(pdMS_TO_TICKS(93));
//     }
// }
// print("FunA: %d\n", MenuPaint::GetSwitchState(0));
// print("FunB: %d\n", MenuPaint::GetSwitchState(1));
// if (MenuPaint::GetSwitchState(0) == 1) {
//     Beep::start();
// } else {
//     Beep::stop();
// }

// [[noreturn]] void vTrackerTask(void *pvParameters) {
//     while (true) {
//         print("Tracker!\n");
//         const TrackerGpio::Data data = TrackerGpio::getData();
//         print("Tracker: %d, %d, %d, %d, %d, %d, %d\n", data.data[0], data.data[1], data.data[2], data.data[3], data.data[4], data.data[5], data.data[6]);
//         vTaskDelay(pdMS_TO_TICKS(1000));
//     }
// }
