#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "Deer/Voxel.h"
#include "Deer/VoxelWorld.h"
#include "DeerRender/GizmoRenderer.h"
#include "DeerRender/Render/Texture.h"
#include "DeerStudio/Editor/EditorUtils.h"
#include "DeerStudio/Editor/Icons.h"
#include "DeerStudio/Editor/Viewport.h"
#include "TerrainEditor.h"
#include "imgui.h"
namespace Deer {
	namespace TerrainEditor {
		VoxelCordinates selectedVoxelStart(-1, -1, -1);
		VoxelCordinates selectedVoxelEnd(-1, -1, -1);
		uint8_t voxelSelectMode = 0;
	}  // namespace TerrainEditor

	void TerrainEditor::boxSelect() {
		ImGui::Separator();
		ImGui::Spacing();
		ImGui::Text("Select mode: ");
		ImGui::SameLine();
		if (voxelSelectMode == FACE_VOXEL_SELECT)
			ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s", "Face");
		else
			ImGui::TextColored(ImVec4(0.5f, 1.0f, 0.6f, 1.0f), "%s", "Voxel");

		ImGui::Separator();
		ImGui::Spacing();
		setupColumns(ICON_BTN_MIN_SIZE + 16);
		if (iconButton((ImTextureID)(uint64_t)
		                   Icons::face_voxel_selection_icon->getTextureID(),
		               ICON_BTN_MIN_SIZE,
		               voxelSelectMode == FACE_VOXEL_SELECT)) {
			voxelSelectMode = FACE_VOXEL_SELECT;
		}
		ImGui::Text("Face");
		ImGui::NextColumn();
		if (iconButton((ImTextureID)(uint64_t)
		                   Icons::internal_voxel_selection_icon->getTextureID(),
		               ICON_BTN_MIN_SIZE,
		               voxelSelectMode == INTERNAL_VOXEL_SELECT)) {
			voxelSelectMode = INTERNAL_VOXEL_SELECT;
		}
		ImGui::Text("Voxel");
		ImGui::Columns();

		if (!viewportIsActive()) {
			if (selectedVoxelStart.isNull()) selectedVoxelStart.makeNull();
			return;
		}

		if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) ||
		    ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
			if (voxelSelectMode == FACE_VOXEL_SELECT) {
				selectedVoxelEnd = voxelFaceRayCoords;
			} else {
				selectedVoxelEnd = voxelRayCoords;
			}
			VoxelWorld::getWorldProps()
			    .clampCordinates(selectedVoxelEnd);
		}

		if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) == 1) {
			selectedVoxelStart = selectedVoxelEnd;
		}

		if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle) == 1) {
			selectedVoxelStart.makeNull();
			selectedVoxelEnd.makeNull();
		}
	}

	void TerrainEditor::boxSelect_Visuals() {
		GizmoRenderer& gizmo = Scene::gizmoRenderer;

		if (!selectedVoxelStart.isNull() && !selectedVoxelEnd.isNull()) {
			VoxelCordinates min;
			VoxelCordinates max;

			if (selectedVoxelEnd.x < selectedVoxelStart.x) {
				min.x = selectedVoxelEnd.x;
				max.x = selectedVoxelStart.x;
			} else {
				max.x = selectedVoxelEnd.x;
				min.x = selectedVoxelStart.x;
			}

			if (selectedVoxelEnd.y < selectedVoxelStart.y) {
				min.y = selectedVoxelEnd.y;
				max.y = selectedVoxelStart.y;
			} else {
				max.y = selectedVoxelEnd.y;
				min.y = selectedVoxelStart.y;
			}

			if (selectedVoxelEnd.z < selectedVoxelStart.z) {
				min.z = selectedVoxelEnd.z;
				max.z = selectedVoxelStart.z;
			} else {
				max.z = selectedVoxelEnd.z;
				min.z = selectedVoxelStart.z;
			}

			int debugVoxel = DataStore::getVoxelID("debug");
			int debugInternal = DataStore::getVoxelID("debug_internal");

			// External faces
			// Z Face
			for (int x = min.x; x <= max.x; x++) {
				for (int y = min.y; y <= max.y; y++) {
					gizmo.drawVoxelFace(x, y, min.z, debugVoxel, NORMAL_BACK,
					                    5);
					gizmo.drawVoxelFace(x, y, max.z, debugVoxel, NORMAL_FRONT,
					                    5);
					gizmo.drawVoxelFaceInverted(x, y, min.z, debugInternal,
					                            NORMAL_BACK, 4);
					gizmo.drawVoxelFaceInverted(x, y, max.z, debugInternal,
					                            NORMAL_FRONT, 4);
				}
			}

			// Y Face
			for (int x = min.x; x <= max.x; x++) {
				for (int z = min.z; z <= max.z; z++) {
					gizmo.drawVoxelFace(x, min.y, z, debugVoxel, NORMAL_DOWN,
					                    5);
					gizmo.drawVoxelFace(x, max.y, z, debugVoxel, NORMAL_UP, 5);
					gizmo.drawVoxelFaceInverted(x, min.y, z, debugInternal,
					                            NORMAL_DOWN, 4);
					gizmo.drawVoxelFaceInverted(x, max.y, z, debugInternal,
					                            NORMAL_UP, 4);
				}
			}

			// X Face
			for (int y = min.y; y <= max.y; y++) {
				for (int z = min.z; z <= max.z; z++) {
					gizmo.drawVoxelFace(min.x, y, z, debugVoxel, NORMAL_LEFT,
					                    5);
					gizmo.drawVoxelFace(max.x, y, z, debugVoxel, NORMAL_RIGHT,
					                    5);
					gizmo.drawVoxelFaceInverted(min.x, y, z, debugInternal,
					                            NORMAL_LEFT, 4);
					gizmo.drawVoxelFaceInverted(max.x, y, z, debugInternal,
					                            NORMAL_RIGHT, 4);
				}
			}
		}
	}
}  // namespace Deer