#include "Nodes_And_Connectors.hpp"
#include "imgui_internal.h"

// 客制化圆形带X按钮
bool CircleButtonWithX(const char *id, float radius)
{
    ImGuiWindow *window = ImGui::GetCurrentWindow();
    if (window->SkipItems)
        return false;

    // 创建ID
    ImGuiID button_id = window->GetID(id);

    // 计算按钮位置和大小
    ImVec2 pos = window->DC.CursorPos;
    ImVec2 size(radius * 2, radius * 2);
    ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));

    // 处理交互
    ImGui::ItemSize(bb);
    if (!ImGui::ItemAdd(bb, button_id))
        return false;

    bool hovered, held;
    bool pressed = ImGui::ButtonBehavior(bb, button_id, &hovered, &held);

    // 绘制
    ImU32 col = ImGui::GetColorU32(
        held ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
                                               : ImGuiCol_Button);

    // 获取绘制列表
    ImDrawList *draw_list = ImGui::GetWindowDrawList();
    ImVec2 center = ImVec2(pos.x + radius, pos.y + radius);

    // 绘制圆形
    draw_list->AddCircleFilled(center, radius, col, 32);

    // 绘制边框（可选）
    draw_list->AddCircle(center, radius, ImGui::GetColorU32(ImGuiCol_Border), 32, 1.0f);

    // 计算X的线条
    float cross_radius = radius * 0.5f; // X的大小
    float thickness = radius * 0.15f;   // X的粗细

    // 绘制X的两条线
    draw_list->AddLine(
        ImVec2(center.x - cross_radius, center.y - cross_radius),
        ImVec2(center.x + cross_radius, center.y + cross_radius),
        ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X
        thickness);
    draw_list->AddLine(
        ImVec2(center.x + cross_radius, center.y - cross_radius),
        ImVec2(center.x - cross_radius, center.y + cross_radius),
        ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X
        thickness);

    return pressed;
}

// =================================================================================================

// 必要构造
Abs_Connector::Abs_Connector(Independent_ID_Generator *ID_Generator,
                             Connector_Type_Enum type,
                             const char *socket_str)
    : ID_Generator(nullptr), id(-1), type(CONNECTOR_TYPE_UNKNOWN), socket_str(nullptr)
{
    // 分配ID
    this->id = ID_Generator->Request_ID();
    if (this->id != -1)
    {
        this->ID_Generator = ID_Generator;
        this->type = type;
        this->socket_str = socket_str;
    }

    // 指针初始化
    this->product = nullptr;
};

// 析构
Abs_Connector::~Abs_Connector()
{
    // 释放产物
    if (this->product != nullptr)
        free(product);
    // 断开所有连接
    this->Disconnect_All();
    // 释放ID
    this->ID_Generator->Release_ID(this->id);
}

// 连接到目标连接点
bool Abs_Connector::Connect_To(Abs_Connector *target)
{
    // 判定接口是否匹配
    if (strcmp(target->socket_str, this->socket_str) == 0)
    {
        // 写连接关系 必须是一收一发
        if (((this->type == CONNECTOR_TYPE_OUTPUT) && (target->type == CONNECTOR_TYPE_INPUT)) || ((this->type == CONNECTOR_TYPE_INPUT) && (target->type == CONNECTOR_TYPE_OUTPUT)))
        {
            // 向双方写入关联信息
            target->related_connector_list.push_back(this);
            this->related_connector_list.push_back(target);
            return true;
        }
    }
    return false;
}

// 断开所有连接
void Abs_Connector::Disconnect_All(void)
{
    for (auto target : this->related_connector_list)
    {
        // 删除连接点对自己的记录
        for (auto iterator = target->related_connector_list.begin(); iterator != target->related_connector_list.end(); iterator++)
            if (*iterator == this)
            {
                iterator = target->related_connector_list.erase(iterator);
                break;
            }
    }

    // 清空自身列表
    decltype(this->related_connector_list) empty_list;
    this->related_connector_list.swap(empty_list);
}

// 与指定的接口断开连接
bool Abs_Connector::Disconnect_To(Abs_Connector *target)
{
    // 查找目标接口
    for (auto iterator = this->related_connector_list.begin(); iterator != this->related_connector_list.end(); iterator++)
    {
        if (*iterator == target)
        {
            // 删除目标连接点对自己的记录
            for (auto iterator = target->related_connector_list.begin(); iterator != target->related_connector_list.end(); iterator++)
                if (*iterator == this)
                {
                    iterator = target->related_connector_list.erase(iterator);
                    break;
                }

            // 自身删除对目标点的记录
            iterator = this->related_connector_list.erase(iterator);
            return true;
        }
    }

    // 未成功查找
    return false;
}

// 注册产物
bool Abs_Connector::Register_Product(void *product, size_t size)
{
    // 非输出类接口
    if (this->type != CONNECTOR_TYPE_OUTPUT)
        return false;

    // 释放之前的产物
    if (this->product != nullptr)
        free(this->product);

    // 分配空间
    this->product = malloc(size);
    if (this->product == nullptr)
        return false;

    // 复制内容
    memcpy(this->product, product, size);
    return true;
}

// 获取上级节点
std::vector<Abs_Connector *> Abs_Connector::Get_Related_List(void)
{
    return this->related_connector_list;
}

// 获取产物
void *Abs_Connector::Get_Product(void)
{
    // 输出节点返回直接产物
    if (this->type == CONNECTOR_TYPE_OUTPUT)
        return this->product;

    // 其它情况返回空值
    return nullptr;
}

// 获取ID
int Abs_Connector::Get_ID(void)
{
    return this->id;
}

// 获取接口类型
Abs_Connector::Connector_Type_Enum Abs_Connector::Get_Type(void)
{
    return this->type;
}

// =================================================================================================

// 必要构造
Abs_Node::Abs_Node(Independent_ID_Generator *Node_ID_Generator,
                   Independent_ID_Generator *Connector_ID_Generator,
                   Node_Type_Enum type,
                   ImVec2 initial_position)
    : Node_ID_Generator(nullptr),
      Connector_ID_Generator(nullptr),
      id(-1),
      type(NODE_TYPE_UNKNOWN),
      initial_position(initial_position)
{
    // 分配ID
    this->id = Node_ID_Generator->Request_ID();

    if (this->id != -1)
    {
        this->Node_ID_Generator = Node_ID_Generator;
        this->Connector_ID_Generator = Connector_ID_Generator;
        this->type = type;
    }

    this->close_flag = false;
}

// 析构
Abs_Node::~Abs_Node()
{
    // 释放ID
    this->Node_ID_Generator->Release_ID(this->id);
}

// 获取ID
int Abs_Node::Get_ID(void)
{
    return this->id;
}

// 获取节点类型
Abs_Node::Node_Type_Enum Abs_Node::Get_Type(void)
{
    return this->type;
}

// 获取关闭信号
bool Abs_Node::Get_CloseFlag(void)
{
    return this->close_flag;
}

// 获取接口列表
std::vector<std::shared_ptr<Abs_Connector>> &Abs_Node::Get_Connector_List(void)
{
    return this->Connector_List;
}

// =================================================================================================

// 必要构造
MSG_InPut_Connector::MSG_InPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_INPUT, "DLT MSG") {}

// 绘制接口
void MSG_InPut_Connector::Show(void)
{
    // 输出接口点
    ImNodes::BeginInputAttribute(this->id, ImNodesPinShape_CircleFilled);
    // 填充占位
    ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight()));
    ImNodes::EndInputAttribute();
}

// 必要构造
MSG_OutPut_Connector::MSG_OutPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "DLT MSG") {}

// 绘制接口
void MSG_OutPut_Connector::Show(void)
{
    // 输出接口点
    ImNodes::BeginOutputAttribute(this->id, ImNodesPinShape_CircleFilled);
    // 填充占位
    ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight()));
    ImNodes::EndOutputAttribute();
}

// 必要构造
CSV_Column_Input_Connector::CSV_Column_Input_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_INPUT, "CSV Column") {}

// 绘制接口
void CSV_Column_Input_Connector::Show()
{
    // 输出接口点
    ImNodes::BeginInputAttribute(this->id, ImNodesPinShape_TriangleFilled);
    // 填充占位
    ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight()));
    ImNodes::EndInputAttribute();
}

// 必要构造
CSV_Column_Output_Connector::CSV_Column_Output_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "CSV Column") {}

// 绘制接口
void CSV_Column_Output_Connector::Show()
{
    // 输出接口点
    ImNodes::BeginOutputAttribute(this->id, ImNodesPinShape_TriangleFilled);
    // 填充占位
    ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight()));
    ImNodes::EndOutputAttribute();
}
// =================================================================================================

// 必要构造
Connector_Test_Node::Connector_Test_Node(Independent_ID_Generator *Node_ID_Generator,
                                         Independent_ID_Generator *Connector_ID_Generator,
                                         ImVec2 initial_position)
    : Abs_Node(Node_ID_Generator,
               Connector_ID_Generator,
               NODE_TYPE_CONNECTOR_TEST,
               initial_position)
{
    // 判定是否成功申请ID , 后加载测试用节点列表
    if (this->id != -1)
    {
        // DLT MSG 相关接口
        this->Connector_List.push_back(std::make_shared<MSG_InPut_Connector>(Connector_ID_Generator));  // [0] -> MSG
        this->Connector_List.push_back(std::make_shared<MSG_OutPut_Connector>(Connector_ID_Generator)); // [1] MSG ->

        // CSV 相关接口
        this->Connector_List.push_back(std::make_shared<CSV_Column_Input_Connector>(Connector_ID_Generator));  // [2] -> Column
        this->Connector_List.push_back(std::make_shared<CSV_Column_Output_Connector>(Connector_ID_Generator)); // [3] -> Column
    }
}

// 绘制节点
void Connector_Test_Node::Show(void)
{

    if (this->close_flag == true)
        return;

    // 初始化位置设定
    if ((this->initial_position.x != 0) || (this->initial_position.y != 0))
    {
        ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position);
        this->initial_position = ImVec2(0, 0);
    }

    // 绘制节点
    ImNodes::BeginNode(this->id);
    {

        // 标题部分
        ImNodes::BeginNodeTitleBar();
        {
            ImGui::Text(u8"接口测试用节点");
            ImGui::SameLine();
            {
                ImGui::TextDisabled(u8"(?)");
                // 上下边距为调整
                ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));

                if (ImGui::BeginItemTooltip())
                {
                    ImGui::Text("Node ID : %d\n", this->id);
                    ImGui::Separator();
                    ImGui::Text(u8"注意！仅供接口测试使用！\n该节点不会进行任何处理操作，且不会生成任何产物");
                    ImGui::EndTooltip();
                }

                ImGui::PopStyleVar();
            }
            ImGui::SameLine();

            // 节点宽度调整
            ImGui::Dummy(ImVec2(120.0f, 0.0f));

            ImGui::SameLine();
            // 绘制关闭按钮
            if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
                this->close_flag = true;
        }
        ImNodes::EndNodeTitleBar();

        // 绘制DLT相关接口组
        {

            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));

            this->Connector_List[0]->Show();
            ImGui::SameLine();
            ImGui::Text("-> DLT-In");
            ImGui::SameLine();
            ImGui::Dummy(ImVec2(ImNodes::GetNodeDimensions(this->id).x - ImGui::CalcTextSize("-> DLT-In").x - ImGui::CalcTextSize("DLT-Out ->").x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f));
            ImGui::SameLine();
            ImGui::Text("DLT-Out ->");
            ImGui::SameLine();
            this->Connector_List[1]->Show();

            ImGui::PopStyleVar();
        }

        // 绘制CSV列相关接口组
        {
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));

            this->Connector_List[2]->Show();
            ImGui::SameLine();
            ImGui::Text("-> CSV-Column-In");
            ImGui::SameLine();
            ImGui::Dummy(ImVec2(ImNodes::GetNodeDimensions(this->id).x - ImGui::CalcTextSize("-> CSV-Column-In").x - ImGui::CalcTextSize("CSV-Column-Out ->").x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f));
            ImGui::SameLine();
            ImGui::Text("CSV-Column-Out ->");
            ImGui::SameLine();
            this->Connector_List[3]->Show();

            ImGui::PopStyleVar();
        }
    }
    ImNodes::EndNode();
}

// 执行处理流程
bool Connector_Test_Node::Execute_Process(void)
{
    return true;
}

// 必要构造
MSG_Input_Node::MSG_Input_Node(Independent_ID_Generator *Node_ID_Generator,
                               Independent_ID_Generator *Connector_ID_Generator,
                               ImVec2 initial_position)
    : Abs_Node(Node_ID_Generator,
               Connector_ID_Generator,
               NODE_TYPE_MSG_LINE_INPUT,
               initial_position)
{
    // 判定是否成功申请ID
    if (this->id != -1)
    {
        // 消息输出节点
        this->Connector_List.push_back(std::make_shared<MSG_OutPut_Connector>(Connector_ID_Generator));
        this->Connector_List.push_back(std::make_shared<MSG_InPut_Connector>(Connector_ID_Generator));
    }
}

// 绘制节点
void MSG_Input_Node::Show(void)
{

    // auto ImNodesStyle = ImNodes::GetStyle();
    // auto ImGuiStyle = ImGui::GetStyle();

    if (this->close_flag == true)
        return;

    // 初始化位置设定
    if ((this->initial_position.x != 0) || (this->initial_position.y != 0))
    {
        ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position);
        this->initial_position = ImVec2(0, 0);
    }

    // 绘制节点
    ImNodes::BeginNode(this->id);
    {

        // 标题部分
        ImNodes::BeginNodeTitleBar();
        {
            ImGui::Text(u8"DLT-信息输入节点");
            ImGui::SameLine();
            {
                ImGui::TextDisabled(u8"(?)");
                // 上下边距为调整
                ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));

                if (ImGui::BeginItemTooltip())
                {
                    ImGui::Text("Node ID : %d\n", this->id);
                    ImGui::Separator();
                    ImGui::Text(u8"每个处理流程开始时，输出一条DLT消息；\n每个此类节点输出的消息均会独立遍历所有输入文件；");
                    ImGui::EndTooltip();
                }

                ImGui::PopStyleVar();
            }
            ImGui::SameLine();
            // ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize(u8"DLT-信息输入节点").x - ImGui::GetTextLineHeight(), 0.0f));

            // 节点宽度调整
            ImGui::Dummy(ImVec2(20.0f, 0.0f));

            ImGui::SameLine();
            // 绘制关闭按钮
            if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
                this->close_flag = true;
        }
        ImNodes::EndNodeTitleBar();

        // 节点主体部分
        {
        }

        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));

        ImVec2 dimension = ImNodes::GetNodeDimensions(this->id);
        ImVec2 text_size = ImGui::CalcTextSize(u8"OUT ->");
        if (dimension.x > text_size.x)
        {
            ImGui::Dummy(ImVec2(dimension.x - text_size.x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f));
            ImGui::SameLine();
        }
        ImGui::Text(u8"OUT ->");
        ImGui::SameLine();

        /**
         * @todo 自定义接口绘制
         */
        for (auto Connector : this->Connector_List)
        {
            Connector->Show();
        }

        ImGui::PopStyleVar();
    }
    ImNodes::EndNode();
}

// 执行处理流程
bool MSG_Input_Node::Execute_Process(void)
{
    return true;
};