#include "Local_Server/Data_Source/Data_Source.h"

#include "SSR/export.h"
#include <filesystem>
#include <iostream>
#include <string>
using namespace Psc;
int max_distance = 700;
namespace fs = std::filesystem;
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 {}
    size_t line_num = 0;
    size_t line_num_ex = 0;
    std::map<std::string, Aircraft_Info*> air_map;
    MY_File_Data_Source(const fs::path& file_path, const fs::path& rel_path) {
        auto u8_string = rel_path.u8string();
        std::string t(u8_string.begin(), u8_string.end());
        auto ttt = file_path.u8string();
        std::string fp(ttt.begin(), ttt.end());
        key = fp;
        std::replace(key.begin(), key.end(), '/', '_');
        std::replace(key.begin(), key.end(), '\\', '_');
        auto path = get_exe_dir() + "/crc_check/" + t;
        this->logger = new BaseLogger(path, 100 * 100 * 10000, 1);
        this->key = key;
        this->data_type = File_Data_Type::BIN_Blank_One_Line_With_Escape;
        this->file_path = fp;
        this->play_mode = Play_Mode::analysis;
        this->open();
    }


    void handle() {
        std::string buffer;
        auto mode_data = read();
        while (!mode_data.empty()) {
            line_num_ex++;
            Binary_Format_handle_buffer(buffer, mode_data, [&](std::string& packet) {

                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) {
                        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) {
                        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) {
                        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) {
                    return; //  这个报文不会解析
                    if (packet.size() != Msg::Radarcape_status_len) {
                        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) {
                        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) {
                    line_num++;
                    auto msg = std::make_shared<Mode_S_Msg>(shared_from_this(), packet);
                    std::optional<CPR::Position> base_station_pos;
                    Mode_S::parse_mode_s_bin(this, msg, base_station_pos);
                }
            });
            mode_data = read();
        }
        this->close();
        std::cout << "line_num: " << line_num << std::endl;
        std::cout << "line_num_ex: " << line_num_ex << std::endl;
    }
};

// "C:/wyc/CLionProjects/plantSunCat/mainProjects/Radarcape/data/pos/110.txt"
void handle(const fs::path& file_path, const fs::path& rel_path) {
    auto fs = std::make_shared<MY_File_Data_Source>(file_path, rel_path);


    Mode_S::parse_ok_json = [&](Aircraft_Info* aircraft_info, Mode_S::P_S mode_s_msg, Psc::JSON json) {

        Log_Type lt({}, {
               {"line:",            std::to_string( fs->line_num) },
            {"df", to_string((int)(mode_s_msg->df))},
               {"icao", mode_s_msg->icao},
               // {"icao_size", std::to_string(mode_s_msg->icao.size())},
                {"hex", mode_s_msg->msg_hex},

                //{"packet", mem2hex(mode_s_msg->packet)},
                {"packet22222222222", mem2hex(packet_to_escape_format(mode_s_msg->packet), true, " ")},
        });



       // fs->logger->debug("", lt, "crc ok");
    };

    Mode_S::parse_call_back = [&](Mode_S::Parse_Call_Back_Type type,
                             Aircraft_Info* aircraft_info,
                             const std::string& field_name_or_error_info,
                             std::vector<std::string> bds_list,
                             void* cur_parser, Mode_S::P_S mode_s_msg
    ) {

        if (type == Mode_S::Parse_Call_Back_Type::Normal_Block) return;

        // Log_Type lt({}, {
        //         {"line",            std::to_string( fs->line_num) },
        //         {"type",            to_string(type) },
        //         {"icao", mode_s_msg->icao},
        //          {"hex", mode_s_msg->msg_hex},
        //          {"df", to_string((int)(mode_s_msg->df))},
        //          {"df", to_string(type)},
        //          {"packet", mem2hex(mode_s_msg->packet)}
        //  });

                auto c1 = crc_hex(mode_s_msg->msg_bin, true);
                // auto c2 = crc_hex(mode_s_msg->msg_bin, false);


                Log_Type lt({}, {
               // {"line:",            std::to_string( fs->line_num) },
            // {"df", to_string((int)(mode_s_msg->df))},
             //   {"icao", mode_s_msg->icao},
               // {"icao_size", std::to_string(mode_s_msg->icao.size())},
             //    {"hex", "\"" + mode_s_msg->msg_hex + "\","},


                {"data", mem2hex(packet_to_escape_format(mode_s_msg->packet), true, " ")},

                {"hex", mode_s_msg->msg_hex },
                {"c1", c1},

                    //{"packet", mem2hex(mode_s_msg->packet)},
        });
        if (type == Mode_S::Parse_Call_Back_Type::CRC_Error) {
            if (mode_s_msg->df == Downlink_Format::Extended_Squitter_17) {
                auto tc = type_code(mode_s_msg->msg_bin);
                lt.set("tc", std::to_string(tc));
            }


            fs->logger->debug("", lt, "");
        }

    };
    fs->handle();
}

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() + "/crc_check/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;
    }
    list_directory(dir_path, dir_path);
    return 0;
}
