#include <nlohmann/json.hpp>
#include "property_editor_color_rect.h"

namespace ECS
{
namespace Items
{
bool ColorRectPropertyEditor::DrawGridSelectorInTableCell(const char *id,
                              ImVec2 &outValue,
                              float cellSize)
{
    bool changed = false;
    static ImVec2 hoveredCell(-1, -1);

    // Push style to ensure consistent spacing
    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));

    ImDrawList *drawList = ImGui::GetWindowDrawList();
    ImVec2 cursorPos = ImGui::GetCursorScreenPos();

    for (int y = 0; y < 10; y++) {
        for (int x = 0; x < 10; x++) {
            ImVec2 cellMin = ImVec2(cursorPos.x + x * cellSize,
                        cursorPos.y + y * cellSize);
            ImVec2 cellMax = ImVec2(cellMin.x + cellSize,
                        cellMin.y + cellSize);

            // Use a dummy for spacing and hit detection
            ImGui::PushID(y * 10 + x);
            ImGui::Dummy(ImVec2(cellSize, cellSize));

            // Check for interaction
            if (ImGui::IsItemHovered()) {
                hoveredCell = ImVec2(x / 9.0f, y / 9.0f);

                if (ImGui::IsMouseClicked(0)) {
                    outValue = hoveredCell;
                    changed = true;
                }
            }
            ImGui::PopID();

            // Draw cell
            bool isSelected = (outValue.x == x / 9.0f &&
                       outValue.y == y / 9.0f);
            bool isHovered = (hoveredCell.x == x / 9.0f &&
                      hoveredCell.y == y / 9.0f);

            ImU32 color;
            if (isSelected)
                color = IM_COL32(100, 150, 255, 255);
            else if (isHovered)
                color = IM_COL32(80, 80, 120, 255);
            else
                color = IM_COL32(60, 60, 70, 255);

            drawList->AddRectFilled(cellMin, cellMax, color);
            drawList->AddRect(cellMin, cellMax,
                      IM_COL32(200, 200, 200, 255));

            if (x < 9)
                ImGui::SameLine();
        }
    }

    // Move cursor past the grid
    ImGui::Dummy(ImVec2(1, 1));

    ImGui::PopStyleVar(2);

    return changed;
}

bool ColorRectPropertyEditor::_matches(const std::string &itemName,
                       const nlohmann::json::json_pointer &ptr,
                       const nlohmann::json &j)
{
    if (ptr.empty())
        return false;
    if (!ptr.parent_pointer().empty() &&
        ptr.parent_pointer().back() == "colorRects") {
        return true;
    }
    return false;
}

void ColorRectPropertyEditor::_render(flecs::entity entity,
                      const nlohmann::json::json_pointer &ptr,
                      nlohmann::json &j)
{
    bool updateMaterial = false;

    ImGui::TableSetColumnIndex(1);
    drawRectPreview(ptr, j);

    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    ImGui::Text("Bounds");
    ImGui::TableSetColumnIndex(1);

    nlohmann::json &d = j[ptr];
    nlohmann::json &c = j[ptr]["color"];

    float bounds[2] = { d["left"], d["top"] };
    if (ImGui::InputFloat("Left", &bounds[0], 0.1f, 0.1f, "%.1f")) {
        d["left"] = std::clamp(std::round(bounds[0] * 10.0f) / 10.0f,
                       0.0f, 1.0f);
        d["right"] = std::clamp(std::round((bounds[0] + 0.1f) * 10.0f) /
                        10.0f,
                    0.0f, 1.0f);
        updateMaterial = true;
    }

    if (ImGui::InputFloat("Top", &bounds[1], 0.1f, 0.1f, "%.1f")) {
        d["top"] = std::clamp(std::round(bounds[1] * 10.0f) / 10.0f,
                      0.0f, 1.0f);
        d["bottom"] = std::clamp(
            std::round((bounds[1] + 0.1f) * 10.0f) / 10.0f, 0.0f,
            1.0f);
        updateMaterial = true;
    }
    ImVec2 value;
    value.x = bounds[0];
    value.y = bounds[1];
    if (DrawGridSelectorInTableCell("##selectRect", value)) {
        bounds[0] = value.x;
        bounds[1] = value.y;
        d["left"] = std::clamp(std::round(bounds[0] * 10.0f) / 10.0f,
                       0.0f, 1.0f);
        d["right"] = std::clamp(std::round((bounds[0] + 0.1f) * 10.0f) /
                        10.0f,
                    0.0f, 1.0f);
        d["top"] = std::clamp(std::round(bounds[1] * 10.0f) / 10.0f,
                      0.0f, 1.0f);
        d["bottom"] = std::clamp(
            std::round((bounds[1] + 0.1f) * 10.0f) / 10.0f, 0.0f,
            1.0f);
        updateMaterial = true;
    }

    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    ImGui::Text("Color");
    ImGui::TableSetColumnIndex(1);

    float col[4] = { c["r"], c["g"], c["b"], c["a"] };
    if (ImGui::ColorEdit4("##color", col)) {
        c["r"] = col[0];
        c["g"] = col[1];
        c["b"] = col[2];
        c["a"] = col[3];
        updateMaterial = true;
    }
    if (updateMaterial) {
        StaticGeometryModule::setItemProperties(entity, j.dump());
        Geometry::createTownMaterial(entity, true);
    }
}

ColorRectPropertyEditor::ColorRectPropertyEditor()
    : DPropertyEditor(EditColorRect, "Color Rect Editor")
{
}

}
}
