/*
 * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
 */

#include <imgui.h>

#include <nostalgia/core/gfx.hpp>
#include <nostalgia/core/media.hpp>
#include <ox/std/memory.hpp>

#include "paletteeditor.hpp"
#include "paletteeditor-imgui.hpp"

namespace nostalgia::core {

ox::Result<PaletteEditorImGui*> PaletteEditorImGui::make(Context *ctx, const ox::String &path) noexcept {
	auto out = ox::UniquePtr<PaletteEditorImGui>(new PaletteEditorImGui);
	out->m_ctx = ctx;
	out->m_itemPath = path;
	const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
	out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
	oxRequire(pal, core::readObj<Palette>(out->m_ctx, out->m_itemPath));
	out->m_pal = *pal.get();
	return out.release();
}

const ox::String &PaletteEditorImGui::itemName() const noexcept {
	return m_itemPath;
}

const ox::String &PaletteEditorImGui::itemDisplayName() const noexcept {
	return m_itemName;
}

void PaletteEditorImGui::draw(core::Context*) noexcept {
	static constexpr auto flags = ImGuiTableFlags_RowBg;
	const auto paneSize = ImGui::GetContentRegionAvail();
	ImGui::BeginChild("PaletteEditor");
	{
		ImGui::BeginChild("Colors", ImVec2(paneSize.x - 200, paneSize.y), false);
		{
			const auto colorsSz = ImGui::GetContentRegionAvail();
			static constexpr auto toolbarHeight = 40;
			ImGui::BeginChild("Toolbar", ImVec2(colorsSz.x, toolbarHeight), true);
			{
				const auto sz = ImVec2(70, 24);
				if (ImGui::Button("Add", sz)) {
					undoStack()->push(new AddColorCommand(&m_pal, 0, m_pal.colors.size()));
				}
				ImGui::SameLine();
				ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size());
				{
					if (ImGui::Button("Remove", sz)) {
						undoStack()->push(new RemoveColorCommand(&m_pal, m_pal.colors[static_cast<std::size_t>(m_selectedRow)], m_selectedRow));
						m_selectedRow = ox::min(m_pal.colors.size() - 1, m_selectedRow);
					}
					ImGui::SameLine();
					ImGui::BeginDisabled(m_selectedRow <= 0);
					{
						if (ImGui::Button("Move Up", sz)) {
							undoStack()->push(new MoveColorCommand(&m_pal, m_selectedRow, -1));
							--m_selectedRow;
						}
					}
					ImGui::EndDisabled();
					ImGui::SameLine();
					ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1);
					{
						if (ImGui::Button("Move Down", sz)) {
							undoStack()->push(new MoveColorCommand(&m_pal, m_selectedRow, 1));
							++m_selectedRow;
						}
					}
					ImGui::EndDisabled();
				}
				ImGui::EndDisabled();
			}
			ImGui::EndChild();
			ImGui::BeginTable("Colors", 5, flags, ImVec2(colorsSz.x, colorsSz.y - (toolbarHeight + 5)));
			{
				ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25);
				ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 50);
				ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 50);
				ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 50);
				ImGui::TableSetupColumn("Color Preview", ImGuiTableColumnFlags_NoHide);
				ImGui::TableHeadersRow();
				for (auto i = 0u; const auto c : m_pal.colors) {
					ImGui::PushID(static_cast<int>(i));
					ImGui::TableNextRow();
					// Color No.
					ImGui::TableNextColumn();
					ImGui::Text("%d", i);
					// Red
					ImGui::TableNextColumn();
					ImGui::Text("%d", red16(c));
					// Green
					ImGui::TableNextColumn();
					ImGui::Text("%d", green16(c));
					// Blue
					ImGui::TableNextColumn();
					ImGui::Text("%d", blue16(c));
					// ColorPreview
					ImGui::TableNextColumn();
					const auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1));
					ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic);
					if (ImGui::Selectable("##ColorRow", i == m_selectedRow, ImGuiSelectableFlags_SpanAllColumns)) {
						m_selectedRow = i;
					}
					ImGui::PopID();
					++i;
				}
			}
			ImGui::EndTable();
		}
		ImGui::EndChild();
		if (m_selectedRow < m_pal.colors.size()) {
			ImGui::SameLine();
			ImGui::BeginChild("ColorEditor", ImVec2(200, paneSize.y), true);
			{
				const auto c = m_pal.colors[m_selectedRow];
				int r = red16(c);
				int g = green16(c);
				int b = blue16(c);
				int a = alpha16(c);
				ImGui::InputInt("Red", &r, 1, 5);
				ImGui::InputInt("Green", &g, 1, 5);
				ImGui::InputInt("Blue", &b, 1, 5);
				const auto newColor = color16(r, g, b, a);
				if (c != newColor) {
					undoStack()->push(new UpdateColorCommand(&m_pal, m_selectedRow, c, newColor));
				}
			}
			ImGui::EndChild();
		}
	}
	ImGui::EndChild();
}

ox::Error PaletteEditorImGui::saveItem() noexcept {
	const auto sctx = applicationData<studio::StudioContext>(m_ctx);
	oxReturnError(sctx->project->writeObj(m_itemPath, &m_pal));
	oxReturnError(m_ctx->assetManager.setAsset(m_itemPath, m_pal));
	return OxError(0);
}

}
