#ifndef PROPERTY_EDITOR_H
#define PROPERTY_EDITOR_H
#include <OgreImGuiOverlay.h>
#include <StaticGeometryModule.h>
#include <string>
#include <nlohmann/json.hpp>
#include <flecs.h>
#include "town.h"

namespace ECS {
namespace Items {

enum EditType {
    EditNone = 0,
    EditString,
    EditMultilineString,
    EditColorRect,
    EditNPC,
    EditFloat,
    EditBool,
    EditInt,
    ViewJson,
    EditItemPosition,
    EditLuaScript,
};
struct PropertyEditor;
void drawRectPreview(nlohmann::json::json_pointer ptr,
             const nlohmann::json &item);

// Property editor definition
struct PropertyEditor {
    int editType;
    std::string name;
    std::function<bool(const std::string &itemName,
               const nlohmann::json::json_pointer &ptr,
               const nlohmann::json &j)>
        matches;
    std::function<void(flecs::entity entity,
               const nlohmann::json::json_pointer &ptr,
               nlohmann::json &j)>
        render;
    std::function<void(flecs::entity entity,
               const nlohmann::json::json_pointer &ptr,
               nlohmann::json &j)>
        apply;
};
struct DPropertyEditor : PropertyEditor {
private:
    virtual bool _matches(const std::string &itemName,
                  const nlohmann::json::json_pointer &ptr,
                  const nlohmann::json &j) = 0;
    virtual void _render(flecs::entity entity,
                 const nlohmann::json::json_pointer &ptr,
                 nlohmann::json &j) = 0;
    virtual void _apply(flecs::entity entity,
                const nlohmann::json::json_pointer &ptr,
                nlohmann::json &j)
    {
    }

public:
    DPropertyEditor(int type, const std::string &name)
    {
        editType = type;
        this->name = name;
        matches = [this](const std::string &itemName,
                 const nlohmann::json::json_pointer &ptr,
                 const nlohmann::json &j) -> bool {
            return _matches(itemName, ptr, j);
        };
        render = [this](flecs::entity entity,
                const nlohmann::json::json_pointer &ptr,
                nlohmann::json &j) { _render(entity, ptr, j); };
        apply = [this](flecs::entity entity,
                   const nlohmann::json::json_pointer &ptr,
                   nlohmann::json &j) { _apply(entity, ptr, j); };
    }
    PropertyEditor getPropertyEditor()
    {
        return { editType, name, matches, render, apply };
    }
    virtual ~DPropertyEditor()
    {
    }
};
void itemsEditorMenu();
void itemsEditorHierarchy();
void itemsEditorProperties();
void itemsEditor();
}
}

#endif // PROPERTY_EDITOR_H
