#include "UI_Layout.hpp"
#include "imgui_impl_win32.h"
#include "Global_Variables.hpp"
#include "Config.hpp"
#include "DLT_Utilities.hpp"

extern "C"
{
#include "windows.h"
#include "stdio.h"
}

#include "thread"

// UI布局
void UI_Layout()
{
    // 配置窗口绘制位置为Dear ImGUI生成的主窗口
    const ImGuiViewport *viewport = ImGui::GetMainViewport();
    // 下一个窗体绘制到主窗体位置
    ImGui::SetNextWindowPos(viewport->WorkPos);
    // 下一个窗体绘制为主窗体大小
    ImGui::SetNextWindowSize(viewport->WorkSize);
    // 设置下一个焦点窗体为主窗体
    ImGui::SetNextWindowViewport(viewport->ID);

    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);   // 绘制风格栈压入窗口圆角为0
    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); // 绘制风格栈压入窗体边框宽度为0

    // 窗体选项配置
    ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
    // 设置窗体相关属性，无标题栏，无折叠标志，不可重塑大小，不可移动
    window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
    // 设置窗体相关属性，收到焦点时不移动到前台，禁用焦点事件
    window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
    // 设置窗体相关属性，不允许停靠
    window_flags |= ImGuiWindowFlags_NoDocking;

    ImGui::Begin("Main Panel", NULL, window_flags); // 创建主面板
    ImGui::PopStyleVar(2);                          // 退出绘制风格栈中的设置项
    {
        const ImGuiStyle &style = ImGui::GetStyle();
        float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));

        // 拖拽输入区域
        Widgets::Drag_Input_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().x / 2 > MAIN_FRAME_SIZE_WIDTH_MIN / 2 ? MAIN_FRAME_SIZE_WIDTH_MIN / 2 : ImGui::GetContentRegionAvail().x / 2));

        // 文件列表组件
        Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));

        // 导出文件
        Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale));
    }
    ImGui::End();

    // ImGui::ShowDemoWindow(nullptr);
}

void Widgets::Drag_Input_Area(const ImVec2 &size)
{
    ImGui::BeginChild("Drag_Drop_Area", size);
    {
        ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 10.0f); // 绘制风格栈压入窗口圆角为0
        ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
        // 显示一个按钮，作为拖拽源
        static bool pressed_hover = false;

        if (ImGui::Button(pressed_hover ? u8"松开左键以添加" : u8"单击选择文件或拖拽文件到此处", ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y)))
        {
            OPENFILENAMEW ofn;                                                 // common dialog box structure
            wchar_t szFile[MAX_PATH * MAX_SINGLE_SELECT_FILE_COUNT] = {L'\0'}; // buffer for file name

            // Initialize OPENFILENAME
            ZeroMemory(&ofn, sizeof(ofn));
            ofn.lStructSize = sizeof(ofn);        // 结构体大小
            ofn.hwndOwner = Main_Window_hWnd;     // 对话框唤起窗体
            ofn.lpstrFile = szFile;               // 输出缓冲区
            ofn.nMaxFile = sizeof(szFile);        // 缓冲区大小
            ofn.lpstrFilter = L"(.dlt)\0*.dlt\0"; // 文件格式筛选器
            ofn.nFilterIndex = 1;                 // 默认选择的筛选器

            // 文件路径必须存在 | 文件本身必须存在 | 允许多文件选择 | 使用资源管理器
            ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER;

            // Display the Open dialog box.

            // 处理文件输入
            if (GetOpenFileNameW(&ofn))
            {
                // 重复输入检测
                bool with_duplicated_input = false;

                wchar_t *p_first_str = ofn.lpstrFile;
                // 单文件
                if ((p_first_str[wcslen(p_first_str)] == L'\0') && (p_first_str[wcslen(p_first_str) + 1] == L'\0'))
                {
                    char file_path_multi_byte[MAX_PATH] = {'\0'};
                    int size_needed = WideCharToMultiByte(CP_UTF8, 0, p_first_str, -1, NULL, 0, NULL, NULL);
                    WideCharToMultiByte(CP_UTF8, 0, p_first_str, -1, file_path_multi_byte, size_needed, NULL, NULL);

                    for (Input_File_Node *p_file_node = input_dlt_file_list_head; p_file_node != nullptr; p_file_node = p_file_node->p_next)
                        if (!strcmp(p_file_node->file_name_str, file_path_multi_byte))
                        {
                            with_duplicated_input = true;
                            break;
                        }
                    if (with_duplicated_input)
                    {
                        MessageBoxW(Main_Window_hWnd, L"存在重复输入", L"", MB_OK | MB_ICONWARNING);
                    }
                    else
                    {

                        // 开辟新文件节点
                        Input_File_Node *p_new_file_node = (Input_File_Node *)malloc(sizeof(Input_File_Node));
                        p_new_file_node->file_name_str = (char *)malloc(strlen(file_path_multi_byte) + 1);
                        memset(p_new_file_node->file_name_str, '\0', strlen(file_path_multi_byte) + 1);
                        memcpy(p_new_file_node->file_name_str, file_path_multi_byte, strlen(file_path_multi_byte) + 1);
                        p_new_file_node->p_next = nullptr;

                        // 插入文件列表
                        if (input_dlt_file_list_head == nullptr)
                            input_dlt_file_list_head = p_new_file_node;
                        else
                        {
                            Input_File_Node *p_target_node = input_dlt_file_list_head;
                            for (size_t count = 1; count < input_dlt_file_count; count++)
                                p_target_node = p_target_node->p_next;

                            p_target_node->p_next = p_new_file_node;
                        }

                        input_dlt_file_count++;
                    }
                }
                else
                {
                    // 多文件输入时
                    char public_path_multi_byte[MAX_PATH] = {'\0'};
                    int size_needed = WideCharToMultiByte(CP_UTF8, 0, p_first_str, -1, NULL, 0, NULL, NULL);
                    WideCharToMultiByte(CP_UTF8, 0, p_first_str, -1, public_path_multi_byte, size_needed, NULL, NULL);

                    for (wchar_t *p_file_name_str = ofn.lpstrFile + wcslen(ofn.lpstrFile) + 1; *p_file_name_str != L'\0'; p_file_name_str += (wcslen(p_file_name_str) + 1))
                    {
                        char file_name_multi_byte[MAX_PATH] = {'\0'};
                        char file_path_multi_byte[MAX_PATH] = {'\0'};
                        int size_needed = WideCharToMultiByte(CP_UTF8, 0, p_file_name_str, -1, NULL, 0, NULL, NULL);
                        WideCharToMultiByte(CP_UTF8, 0, p_file_name_str, -1, file_name_multi_byte, size_needed, NULL, NULL);

                        // 拼接完整路径
                        sprintf(file_path_multi_byte, "%s\\%s", public_path_multi_byte, file_name_multi_byte);

                        for (Input_File_Node *p_file_node = input_dlt_file_list_head; p_file_node != nullptr; p_file_node = p_file_node->p_next)
                            if (!strcmp(p_file_node->file_name_str, file_path_multi_byte))
                            {
                                with_duplicated_input = true;
                                break;
                            }
                        if (with_duplicated_input)
                            continue;

                        // 开辟新文件节点
                        Input_File_Node *p_new_file_node = (Input_File_Node *)malloc(sizeof(Input_File_Node));
                        p_new_file_node->file_name_str = (char *)malloc(strlen(file_path_multi_byte) + 1);
                        memset(p_new_file_node->file_name_str, '\0', strlen(file_path_multi_byte) + 1);
                        memcpy(p_new_file_node->file_name_str, file_path_multi_byte, strlen(file_path_multi_byte) + 1);
                        p_new_file_node->p_next = nullptr;

                        // 插入文件列表
                        if (input_dlt_file_list_head == nullptr)
                            input_dlt_file_list_head = p_new_file_node;
                        else
                        {
                            Input_File_Node *p_target_node = input_dlt_file_list_head;
                            for (size_t count = 1; count < input_dlt_file_count; count++)
                                p_target_node = p_target_node->p_next;

                            p_target_node->p_next = p_new_file_node;
                        }

                        input_dlt_file_count++;
                    }

                    if (with_duplicated_input)
                    {
                        MessageBoxW(Main_Window_hWnd, L"存在重复输入", L"", MB_OK);
                    }
                }
            }
        }
        // 仅在外部拖拽入内时触发，内部拖拽不触发
        pressed_hover = (ImGui::IsItemHovered() && (GetAsyncKeyState(VK_LBUTTON) < 0) && (!ImGui::IsMouseDown(ImGuiMouseButton_Left)));

        ImGui::PopStyleVar(2);
    }
    ImGui::EndChild();
}

void Widgets::File_List_Area(const ImVec2 &size)
{
    ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
    ImGui::BeginChild("File_List_Area_Wrapper", size, ImGuiChildFlags_Border);
    ImGui::PopStyleVar();
    {

        int element_id = 0;
        Input_File_Node *p_file_node_pre = nullptr;
        Input_File_Node *p_file_node = input_dlt_file_list_head;
        for (size_t count = 0; count < input_dlt_file_count; count++)
        {
            ImGui::PushID(element_id++);

            // 点击了删除
            if (ImGui::Button("X"))
            {
                if (p_file_node == input_dlt_file_list_head)
                {
                    free(input_dlt_file_list_head->file_name_str);
                    input_dlt_file_list_head = input_dlt_file_list_head->p_next;
                    free(p_file_node);
                    p_file_node = input_dlt_file_list_head;
                }
                else
                {
                    p_file_node_pre->p_next = p_file_node->p_next;
                    free(p_file_node->file_name_str);
                    free(p_file_node);
                }
                input_dlt_file_count--;
                count--;
                ImGui::PopID();
                continue;
            }

            ImGui::SameLine();

            ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
            ImGui::InputText("##Text_Show", p_file_node->file_name_str, strlen(p_file_node->file_name_str) + 1, ImGuiInputTextFlags_ElideLeft | ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoUndoRedo);

            ImGui::PopID();

            p_file_node = p_file_node->p_next;
            if (count == 0)
                p_file_node_pre = input_dlt_file_list_head;
            else
                p_file_node_pre = p_file_node_pre->p_next;
        }
    }
    ImGui::EndChild();
}

void Widgets::Workflow_Area(const ImVec2 &size)
{
    ImNodes::BeginNodeEditor();
    {

        ImNodes::BeginNode(1);

        ImNodes::BeginNodeTitleBar();
        ImGui::TextUnformatted("output node");
        ImNodes::EndNodeTitleBar();

        ImGui::Text("Test Format %%d :%d", 123);

        ImGui::Button("Click");

        ImGui::SameLine();
        static bool check = false;
        ImGui::Checkbox("", &check);

        ImNodes::EndNode();
    }
    ImNodes::EndNodeEditor();
}

void Widgets::Control_Panel(const ImVec2 &size)
{
    ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
    ImGui::BeginChild("Control_Panel", size, ImGuiChildFlags_Border);
    ImGui::PopStyleVar(2);
    {
        static bool export_confirmed = false;
        static bool export_task_created = false;
        static char export_file_path_str[MAX_PATH] = {'\0'};

        if (!export_confirmed)
        {
            ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 10.0f);
            if (ImGui::Button(u8"导出", ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y)))
            {
                if (input_dlt_file_list_head == nullptr)
                    MessageBoxW(Main_Window_hWnd, L"需要至少输入一个文件", L"", MB_OK | MB_ICONERROR);
                else
                {
                    OPENFILENAMEW ofn;                         // common dialog box structure
                    static wchar_t szFile[MAX_PATH] = {L'\0'}; // buffer for file name

                    // Initialize OPENFILENAME
                    ZeroMemory(&ofn, sizeof(ofn));
                    ofn.lStructSize = sizeof(ofn);        // 结构体大小
                    ofn.hwndOwner = Main_Window_hWnd;     // 对话框唤起窗体
                    ofn.lpstrFile = szFile;               // 输出缓冲区
                    ofn.nMaxFile = sizeof(szFile);        // 缓冲区大小
                    ofn.lpstrFilter = L"(.csv)\0*.csv\0"; // 文件格式筛选器
                    ofn.nFilterIndex = 1;                 // 默认选择的筛选器

                    // 文件路径必须存在 | 文件本身必须存在 | 使用资源管理器
                    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;

                    if (GetSaveFileNameW(&ofn))
                    {
                        // 提取文件路径
                        memset(export_file_path_str, '\0', sizeof(export_file_path_str));
                        int size_needed = WideCharToMultiByte(CP_UTF8, 0, szFile, -1, NULL, 0, NULL, NULL);
                        WideCharToMultiByte(CP_UTF8, 0, szFile, -1, export_file_path_str, size_needed, NULL, NULL);

                        wchar_t File_Name[MAX_PATH] = {L'\0'};
                        wchar_t *p_str_end = szFile + wcslen(szFile);

                        // 处理后缀
                        char *p_extension_name = export_file_path_str + (strlen(export_file_path_str) - 4);

                        if (p_extension_name[0] != '.' || toupper(p_extension_name[1]) != 'C' || toupper(p_extension_name[2]) != 'S' || toupper(p_extension_name[3]) != 'V')
                        {
                            p_extension_name += 4;
                            p_extension_name[0] = '.';
                            p_extension_name[1] = 'c';
                            p_extension_name[2] = 's';
                            p_extension_name[3] = 'v';

                            p_str_end[0] = L'.';
                            p_str_end[1] = L'c';
                            p_str_end[2] = L's';
                            p_str_end[3] = L'v';
                        }

                        while (p_str_end != szFile && *(p_str_end - 1) != L'\\')
                            p_str_end--;

                        size_t len = wcslen(p_str_end);
                        for (size_t count = 0; count < len; count++, p_str_end++)
                            File_Name[count] = *p_str_end;

                        memcpy(szFile, File_Name, sizeof(File_Name));

                        // 判定是否覆盖文件
                        FILE *p_file = fopen(export_file_path_str, "rb");
                        if (p_file != nullptr)
                        {
                            fclose(p_file);
                            if (MessageBoxW(Main_Window_hWnd, L"文件已存在，是否覆盖?", L"", MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES)
                                export_confirmed = true;
                        }
                        else
                            export_confirmed = true;
                    }
                }
            }
            ImGui::PopStyleVar();
        }
        else
        {
            // 创建导出任务
            if (!export_task_created)
            {
                export_task_created = true;

                // 执行导出任务的线程
                std::thread export_thread(
                    [&]()
                    {
                        DLT_Log Log;
                        Input_File_Node *p_file_list = input_dlt_file_list_head;
                        DLT_Type::DLT_Err err;

                        while (p_file_list != nullptr)
                        {
                            err = Log.load_from_file(p_file_list->file_name_str);
                            if (err != DLT_Type::DLT_ERROR_NONE)
                                break;
                            p_file_list = p_file_list->p_next;
                        }

                        if (err != DLT_Type::DLT_ERROR_NONE)
                        {
                            switch (err)
                            {
                            case DLT_Type::DLT_ERROR_FILE_OPEN_FAILED: // 文件打开失败
                                MessageBoxW(Main_Window_hWnd, L"文件打开失败，检查路径是否存在特殊字符", L"", MB_OK | MB_ICONERROR);
                                break;
                            default:
                                MessageBoxW(Main_Window_hWnd, L"文件加载失败", L"", MB_OK | MB_ICONERROR);
                            }
                        }
                        else
                        {
                            // 排序后导出
                            Log.sort_msg_list();
                            err = Log.export_to_csv(export_file_path_str);

                            if (err == DLT_Type::DLT_ERROR_NONE)
                                MessageBoxW(Main_Window_hWnd, L"导出完成", L"", MB_OK);
                            else
                                MessageBoxW(Main_Window_hWnd, L"导出失败，检查文件占用", L"", MB_OK | MB_ICONERROR);
                        }
                        export_confirmed = false;
                        export_task_created = false;
                    });

                // 分离线程
                export_thread.detach();
            }

            ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.5f);
            ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y), u8"正在导出...");
            ImGui::PopStyleVar();
        }
    }
    ImGui::EndChild();
}