#include "ProceduralMaterialEditor.hpp"
#include "../components/ProceduralTexture.hpp"
#include <imgui.h>

ProceduralMaterialEditor::ProceduralMaterialEditor(Ogre::SceneManager *sceneMgr)
	: m_sceneMgr(sceneMgr)
{
}

void ProceduralMaterialEditor::renderTextureSelector(
	flecs::entity entity, ProceduralMaterialComponent &material)
{
	// Get the world from the entity
	flecs::world world = entity.world();

	// Collect all entities with ProceduralTextureComponent
	std::vector<flecs::entity> textureEntities;
	std::vector<std::string> textureNames;
	std::vector<std::string> displayNames;

	int currentIndex = -1;
	int noneIndex = 0;

	// Add "None" option
	displayNames.push_back("None");
	textureEntities.push_back(flecs::entity::null());
	textureNames.push_back("");

	world.query<ProceduralTextureComponent>().each(
		[&](flecs::entity e, ProceduralTextureComponent &texture) {
			textureEntities.push_back(e);

			std::string name =
				texture.textureName.empty() ?
					"Texture " + std::to_string(e.id()) :
					texture.textureName;
			textureNames.push_back(name);

			// Build display name
			std::string display = name;
			if (texture.generated) {
				display += " (generated)";
			} else {
				display += " (pending)";
			}
			displayNames.push_back(display);

			if (material.diffuseTextureEntity == e) {
				currentIndex = (int)textureEntities.size() - 1;
			}
		});

	// Default to none if not found
	if (currentIndex == -1) {
		currentIndex = noneIndex;
	}

	// Build combo string
	std::string comboItems;
	for (size_t i = 0; i < displayNames.size(); ++i) {
		if (i > 0)
			comboItems += '\0';
		comboItems += displayNames[i];
	}
	comboItems += '\0';

	int newIndex = currentIndex;
	if (ImGui::Combo("Diffuse Texture", &newIndex, comboItems.c_str())) {
		if (newIndex >= 0 && newIndex < (int)textureEntities.size()) {
			if (newIndex == noneIndex) {
				material.diffuseTextureEntity =
					flecs::entity::null();
				material.diffuseTextureId = "";
			} else {
				material.diffuseTextureEntity =
					textureEntities[newIndex];
				// Also store the persistent texture ID
				if (material.diffuseTextureEntity.is_alive() &&
				    material.diffuseTextureEntity
					    .has<ProceduralTextureComponent>()) {
					const auto &texture =
						material.diffuseTextureEntity.get<
							ProceduralTextureComponent>();
					material.diffuseTextureId =
						texture.textureId;
				} else {
					material.diffuseTextureId = "";
				}
			}
			material.markDirty();
		}
	}

	// Show warning if no textures available
	if (textureEntities.size() <= 1) {
		ImGui::TextColored(ImVec4(1, 0.5f, 0, 1),
				   "Create a Procedural Texture first!");
	}
}

bool ProceduralMaterialEditor::renderComponent(
	flecs::entity entity, ProceduralMaterialComponent &material)
{
	bool modified = false;

	if (ImGui::CollapsingHeader("Procedural Material",
				    ImGuiTreeNodeFlags_DefaultOpen)) {
		ImGui::Indent();

		// Material info
		if (material.created) {
			ImGui::TextColored(ImVec4(0, 1, 0, 1),
					   "Status: Created");
			ImGui::Text("Material: %s",
				    material.materialName.c_str());
		} else if (material.dirty) {
			ImGui::TextColored(ImVec4(1, 1, 0, 1),
					   "Status: Needs Creation");
		} else {
			ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1),
					   "Status: Not Created");
		}

		ImGui::Separator();

		// Material name
		char nameBuf[256];
		strncpy(nameBuf, material.materialName.c_str(),
			sizeof(nameBuf) - 1);
		nameBuf[sizeof(nameBuf) - 1] = '\0';

		if (ImGui::InputText("Material Name", nameBuf,
				     sizeof(nameBuf))) {
			material.materialName = nameBuf;
			material.markDirty();
			modified = true;
		}
		ImGui::TextDisabled("(Leave empty for auto-generated name)");

		ImGui::Separator();

		// Diffuse texture selector
		renderTextureSelector(entity, material);

		ImGui::Separator();

		// Material colors
		ImGui::Text("Material Properties:");

		if (ImGui::ColorEdit3("Ambient", material.ambient)) {
			material.markDirty();
			modified = true;
		}

		if (ImGui::ColorEdit3("Diffuse Multiplier", material.diffuse)) {
			material.markDirty();
			modified = true;
		}

		if (ImGui::ColorEdit3("Specular", material.specular)) {
			material.markDirty();
			modified = true;
		}

		if (ImGui::SliderFloat("Shininess", &material.shininess, 1.0f,
				       128.0f)) {
			material.markDirty();
			modified = true;
		}

		if (ImGui::SliderFloat("Roughness", &material.roughness, 0.0f,
				       1.0f)) {
			material.markDirty();
			modified = true;
		}

		ImGui::Separator();

		// Recreate button
		if (ImGui::Button("Recreate Material")) {
			material.markDirty();
			modified = true;
		}

		ImGui::SameLine();

		// Reset to defaults
		if (ImGui::Button("Reset to Defaults")) {
			material.ambient[0] = 0.2f;
			material.ambient[1] = 0.2f;
			material.ambient[2] = 0.2f;
			material.diffuse[0] = 1.0f;
			material.diffuse[1] = 1.0f;
			material.diffuse[2] = 1.0f;
			material.specular[0] = 0.0f;
			material.specular[1] = 0.0f;
			material.specular[2] = 0.0f;
			material.shininess = 32.0f;
			material.roughness = 0.5f;
			material.markDirty();
			modified = true;
		}

		ImGui::Unindent();
	}

	return modified;
}
