#include <filesystem>
#include <iostream>
#include <string>
#include "Local_Server/Data_Source.h"
#include "Local_Server/Data_Source.h"
#include "SSR/export.h"
using namespace Psc;
int max_distance = 700;
class MY_File_Data_Source : public File_Data_Source {
public:
    BaseLogger* logger{};
    void pre_handle(const std::string& data) override {}
    void handle_mode_s(std::string& packet) override {}
};
std::map<std::string, Aircraft_Info*> air_map;
static size_t line_num = 0;
static size_t line_num_ex = 0;
namespace fs = std::filesystem;
// "C:/wyc/CLionProjects/plantSunCat/mainProjects/Radarcape/data/pos/110.txt"
void handle(const fs::path& file_path, const fs::path& rel_path) {
    line_num = 0;
    line_num_ex = 0;
    MY_File_Data_Source fs;
    auto u8_string = rel_path.u8string();
    std::string t(u8_string.begin(), u8_string.end());
    auto path = get_exe_dir() + "/tarck_logs/" + t;
    auto ttt = file_path.u8string();
    std::string fp(ttt.begin(), ttt.end());
    auto key = fp;
    std::replace(key.begin(), key.end(), '/', '_');
    std::replace(key.begin(), key.end(), '\\', '_');
    fs.logger = new BaseLogger(path, 100 * 100 * 10000, 1);
    fs.key = key;
    fs.data_type = Mock_Data_Type::BIN_Blank_One_Line_With_Escape;
    fs.file_path = fp;
    fs.play_mode = Play_Mode::analysis;
    fs.open();
    std::string buffer;
    auto mode_data = fs.read();
    while (!mode_data.empty()) {
        line_num_ex++;
        Binary_Format_handle_buffer(buffer, mode_data, [&](std::string& packet) {
            line_num++;
            if (packet[0] != 0x1a) {
                std::cout << "first:" << mem2hex(packet) << std::endl;
                return;
            }
            std::string error_len = key + "  " + LOG_POS_SIMPLE + " mode_s_error_length";
            auto type = packet[1];
            if (type == Msg::AC) {
                if (packet.size() != Msg::AC_len) {
                    fs.logger->c_debug(error_len, {},
                                       std::to_string(type) + " size:" + std::to_string(packet.size()) + " hex:" +
                                       mem2hex(packet) + "  should:" + std::to_string(Msg::AC_len));
                    return;
                }
            } else if (type == Msg::S7) {
                if (packet.size() != Mode_S_Msg::S7_len) {
                    fs.logger->c_debug(error_len, {},
                                       std::to_string(type) + " size:" + std::to_string(packet.size()) + " hex:" +
                                       mem2hex(packet) + "  should:" + std::to_string(Msg::S7_len));
                    return;
                }
            } else if (type == Msg::S14) {
                if (packet.size() != Msg::S14_len) {
                    fs.logger->c_debug(error_len, {},
                                       std::to_string(type) + " size:" + std::to_string(packet.size()) + " hex:" +
                                       mem2hex(packet) + "  should:" + std::to_string(Msg::S14_len));
                    return;
                }
            } else if (type == Msg::Radarcape_status) {
                if (packet.size() != Msg::Radarcape_status_len) {
                    fs.logger->c_debug(error_len, {},
                                       std::to_string(type) + " size:" + std::to_string(packet.size()) + " hex:" +
                                       mem2hex(packet) + "  should:" + std::to_string(Msg::Radarcape_status_len));
                    return;
                }
            } else if (type == Msg::HULC_Status) {
                if (packet.size() != Msg::HULC_len) {
                    fs.logger->c_debug(error_len, {},
                                       std::to_string(type) + "  HULC size:" + std::to_string(packet.size()) + " hex:" +
                                       mem2hex(packet));
                    return;
                }
            } else {
                // std::cout << "unknown_type:" << mem2hex(packet);
                rotating_log("unknown_type", mem2hex(packet));
                return;
            }
            bool mode_s = type == Msg::S7 || type == Msg::S14;
            if (!mode_s) {}
            if (type == Msg::AC) {} else if (type == Msg::HULC_Status) {} else if (type == Msg::Radarcape_status) {
                auto msg = create_Radarcape_STATUS_Message(packet);
                std::cout << msg.toJson().to_json_string() << std::endl;
                fs.logger->debug("Radarcape_status/radarcape", {}, msg.toJson().to_json_string());
            } else if (mode_s) {
                // 拓展点
                auto mode_s_msg = std::make_unique<Mode_S_Msg>(nullptr, packet);
                std::string& msg_hex = mode_s_msg->msg_hex;
                std::string msg_bin = hex2bin(mode_s_msg->msg_hex);
                auto df = ::decode_df(msg_bin);
                std::string icao = ::decode_icao(msg_bin);
                JSON msg_json = JSON::object();
                MLAT_timestamp* mlat_timestamp = &mode_s_msg->mlat_timestamp;
                Log_Type lt({}, {
                                {"行号", std::to_string(line_num)},
                                {"ICAO", icao},
                                //{"DF", std::to_string(static_cast<int>(df))},
                                {"signal_level", std::to_string((int)mode_s_msg->signal_level)},
                                {"时间戳", mode_s_msg->mlat_timestamp.to_string()},
                                //{"msg_hex", msg_hex},
                                {"msg_hex_blank", mem2hex(hex2mem(msg_hex), true, " ")}
                            });
                lt.new_line = true;
                //fs.logger->debug("收到报文", lt, "");
                if (mode_s_msg->df == Downlink_Format::Extended_Squitter_17) {
                    if (!with_PI::check_crc(msg_bin, icao)) {
                        fs.logger->error("crc_error", lt.append("pos", LOG_POS_SIMPLE), "");
                        return;
                    }
                    int tc = type_code(msg_bin);
                    auto& icao = mode_s_msg->icao;
                    if (air_map.find(icao) == air_map.end()) {
                        auto i = new Aircraft_Info(icao);
                        air_map[icao] = i;
                    }
                    auto& info = *air_map[mode_s_msg->icao];
                    // if (tc >= 5 && tc <= 8) {
                    //     auto& tt = info.BDS06_surface_position.value;
                    //     if (!tt.has_value()) {
                    //         tt = typename std::remove_reference_t<decltype(tt)>::value_type();
                    //     }
                    //     auto& t = tt.value();
                    //     info.refresh_pos(true);
                    //     t.base_station_pos = CPR::Position{37, 121};
                    //     t.parse(msg_bin);
                    //     auto p = t.parse_message(msg_bin, static_cast<time_t>(mlat_timestamp->daysec), max_distance);
                    //     if (p.has_value()) {
                    //         info.surface_pos_track_list.push(p.value());
                    //         std::cout << "第一次出现地面轨迹  手动崩溃!" << std::endl;
                    //         std::exit(0);
                    //         fs.logger->debug("surface/地面轨迹", lt, info.surface_pos_track_list.to_string());
                    //     }
                    //     msg_json.append_list(t.toJson().children);
                    // } else
                    if ((tc >= 9 && tc <= 18) || (tc >= 20 && tc <= 22)) {
                        auto& tt = info.BDS05_airborne_position.value;
                        if (!tt.has_value()) {
                            tt = typename std::remove_reference_t<decltype(tt)>::value_type();
                        }
                        auto& t = tt.value();
                        t.parse(msg_bin);
                        info.refresh_pos(true);
                        auto p = t.parse_message(msg_bin, static_cast<time_t>(mlat_timestamp->daysec), max_distance);
                        if (p.has_value()) {
                            double meter = t.get_alt_meter();
                            double x, y, z;
                            CPR::WGS84_LBH_to_XYZ(p->lon, p->lat, meter, x, y, z);
                            std::ostringstream oss;
                            oss << std::fixed << std::setprecision(10);
                            oss << std::endl;
                            oss << "经度-纬度-高度(m)" << "[" << p->lon << ", " << p->lat << ", " << meter << "]" <<
                                std::endl;
                            oss << "笛卡尔坐标系：" << "[" << x << ", " << y << ", " << z << "]" << "   Altitude_type:" <<
                                to_string<Altitude_type>(t.get_altitude_type()) << std::endl;
                            fs.logger->debug("坐标解析成功", lt, oss.str());
                            Position_3D p2(p->lat, p->lon, 0);
                            info.air_pos_track_list.push(p2);
                        } else {
                            fs.logger->debug("坐标解析失败", lt, "\n");
                        }
                        msg_json.append_list(t.toJson().children);
                    } else {
                        lt.append("tc", std::to_string(tc));
                        fs.logger->debug("未知的tc", lt, "\n");
                    }
                }
            }
        });
        mode_data = fs.read();
    }
    std::cout << "line_num: " << line_num << std::endl;
    std::cout << "line_num_ex: " << line_num_ex << std::endl;
    fs.close();
}
// void list_directory(const fs::path& dir_path, const std::string& relative_path = "") {
//     for (const auto& entry : fs::directory_iterator(dir_path)) {
//         std::string file_path = entry.path().string();
//         std::string filename = entry.path().filename().string();
//         std::string full_relative_path = relative_path.empty() ? filename : relative_path + "/" + filename;
//         if (fs::is_directory(entry.status())) {
//             list_directory(dir_path, full_relative_path);  // 递归遍历子目录
//         } else {
//             handle(file_path, full_relative_path + filename);  // 对文件进行处理
//         }
//     }
// }
void list_directory(const fs::path& dir_path, const fs::path& base_path) {
    for (const auto& entry : fs::directory_iterator(dir_path)) {
        fs::path file_path = entry.path();
        auto relative_path = fs::relative(file_path, base_path); // 计算相对路径
        if (fs::is_directory(entry.status())) {
            list_directory(file_path, base_path); // 递归遍历子目录
        } else {
            std::cout << "Full path: " << (const char*)file_path.u8string().c_str() << std::endl; // 输出完整路径
            std::cout << "Relative path: " << (const char*)relative_path.u8string().c_str() << std::endl; // 输出相对路径
            handle(file_path, relative_path);
        }
    }
}
std::wstring _transformString2Wstring(const std::string& s) {
    setlocale(LC_CTYPE, "en_US.UTF-8");
    const char* _Source = s.c_str();
    size_t len = strlen(_Source) + 1;
    size_t converted = 0;
    wchar_t* wStr = new wchar_t[len];
    mbstowcs_s(&converted, wStr, len, _Source, _TRUNCATE);
    std::wstring result(wStr);
    delete[] wStr;
    return result;
}
std::wstring gbk_to_wstring(const std::string& gbk) {
    int len = MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, nullptr, 0);
    std::wstring wstr(len, L'\0');
    MultiByteToWideChar(CP_ACP, 0, gbk.c_str(), -1, &wstr[0], len);
    // 去掉末尾'\0'
    if (!wstr.empty() && wstr.back() == L'\0') wstr.pop_back();
    return wstr;
}
int main(int argc, char* argv[]) {
    // 检查命令行参数是否提供了目录路径
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <directory_path>" << std::endl;
        return 1;
    }
    set_console_utf8();
    Base_Logger_Manager::instance().init();
    auto path = Psc::get_exe_dir() + "/tarck_logs/mode_s.log";
    mode_s_logger = new BaseLogger(path, 100 * 100 * 10000, 1);
    std::string aaa = argv[1];
    std::u8string dp((char8_t*)platform_2_utf8(aaa).data());
    auto dir_path = std::filesystem::path(dp);
    if (!fs::exists(dir_path)) {
        std::cerr << "!fs::exists(pa)." << std::endl;
        return 1;
    }
    if (!fs::is_directory(dir_path)) {
        std::cerr << "!fs::is_directory(pa)." << std::endl;
        return 1;
    }
    // 遍历目录下的所有文件
    // for (const auto& entry : fs::directory_iterator(dir_path)) {
    //     std::string file_path = entry.path().string();
    //     std::string filename = entry.path().filename().string();
    //     std::cout << "Full path: " << file_path << std::endl;
    //     std::cout << "File name: " << filename << std::endl;
    //     handle(file_path, filename);
    // }
    list_directory(dir_path, dir_path);
    return 0;
}
// std::vector<std::string> maybe_dir_path_list {
//     dir_path,
//     gbk_to_utf8(dir_path)
// };
// bool find = false;
// for (auto& maybe_dir_path : maybe_dir_path_list) {
//     if (fs::exists(maybe_dir_path) && fs::is_directory(maybe_dir_path)) {
//         dir_path = maybe_dir_path;
//         find = true;
//         break;
//     }
// }
// if (!find) {
//     std::cerr << "The path does not exist or is not a directory." << std::endl;
//     return 1;
// }
