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

#include <imgui.h>

#include <turbine/gfx.hpp>

#include <studio/imguiutil.hpp>

namespace studio::ig {

ChildStackItem::ChildStackItem(ox::CStringView id, ImVec2 const&sz) noexcept {
	ImGui::BeginChild(id.c_str(), sz);
}

ChildStackItem::~ChildStackItem() noexcept {
	ImGui::EndChild();
}

IDStackItem::IDStackItem(int id) noexcept {
	ImGui::PushID(id);
}

IDStackItem::IDStackItem(const char *id) noexcept {
	ImGui::PushID(id);
}

IDStackItem::IDStackItem(ox::CStringView id) noexcept: IDStackItem(id.c_str()) {}

IDStackItem::~IDStackItem() noexcept {
	ImGui::PopID();
}


IndentStackItem::IndentStackItem(float indent) noexcept: m_indent(indent) {
	ImGui::Indent(m_indent);
}

IndentStackItem::~IndentStackItem() noexcept {
	ImGui::Indent(-m_indent);
}


void centerNextWindow(turbine::Context &ctx) noexcept {
	auto const sz = turbine::getScreenSize(ctx);
	auto const screenW = static_cast<float>(sz.width);
	auto const screenH = static_cast<float>(sz.height);
	auto const mod = ImGui::GetWindowDpiScale() * 2;
	ImGui::SetNextWindowPos(ImVec2(screenW / mod, screenH / mod), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
}

bool PushButton(ox::CStringView lbl, ImVec2 const&btnSz) noexcept {
	return ImGui::Button(lbl.c_str(), btnSz);
}

PopupResponse PopupControlsOkCancel(float popupWidth, bool &popupOpen) {
	auto out = PopupResponse::None;
	constexpr auto btnSz = ImVec2{50, BtnSz.y};
	ImGui::Separator();
	ImGui::SetCursorPosX(popupWidth - 118);
	if (ImGui::Button("OK", btnSz)) {
		ImGui::CloseCurrentPopup();
		popupOpen = false;
		out = PopupResponse::OK;
	}
	ImGui::SameLine();
	if (ImGui::IsKeyDown(ImGuiKey_Escape) || ImGui::Button("Cancel", btnSz)) {
		ImGui::CloseCurrentPopup();
		popupOpen = false;
		out = PopupResponse::Cancel;
	}
	return out;
}

bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, ImVec2 const&sz) {
	constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
	ig::centerNextWindow(ctx);
	ImGui::OpenPopup(popupName.c_str());
	ImGui::SetNextWindowSize(sz);
	return ImGui::BeginPopupModal(popupName.c_str(), &show, modalFlags);
}

bool ComboBox(
		ox::CStringView lbl,
		ox::SpanView<ox::String> list,
		size_t &selectedIdx) noexcept {
	bool out{};
	auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
	if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
		for (auto i = 0u; i < list.size(); ++i) {
			const auto selected = (selectedIdx == i);
			if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
				selectedIdx = i;
				out = true;
			}
		}
		ImGui::EndCombo();
	}
	return out;
}

bool FileComboBox(
		ox::CStringView lbl,
		studio::StudioContext &sctx,
		ox::StringView fileExt,
		size_t &selectedIdx) noexcept {
	auto const&list = sctx.project->fileList(fileExt);
	bool out{};
	auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
	if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
		for (auto i = 0u; i < list.size(); ++i) {
			const auto selected = (selectedIdx == i);
			if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
				selectedIdx = i;
				out = true;
			}
		}
		ImGui::EndCombo();
	}
	return out;
}

bool ListBox(
		ox::CStringView name,
		std::function<ox::CStringView(size_t)> const&f,
		size_t strCnt,
		size_t &selIdx) noexcept {
	auto out = false;
	if (ImGui::BeginListBox(name.c_str())) {
		for (auto i = 0u; i < strCnt; ++i) {
			auto str = f(i);
			ig::IDStackItem const idStackItem2(static_cast<int>(i));
			if (ImGui::Selectable(str.c_str(), selIdx == i)) {
				if (i != selIdx) {
					selIdx = i;
					out = true;
				}
			}
		}
		ImGui::EndListBox();
	}
	return out;
}

bool ListBox(ox::CStringView name, ox::SpanView<ox::String> const&list, size_t &selIdx) noexcept {
	return ig::ListBox(name, [list](size_t i) -> ox::CStringView {
		return list[i];
	}, list.size(), selIdx);
}


FilePicker::FilePicker(
		studio::StudioContext &sctx,
		ox::String title,
		ox::String fileExt,
		ImVec2 const&size) noexcept:
	m_sctx(sctx),
	m_title(std::move(title)),
	m_fileExt(std::move(fileExt)),
	m_size(size) {
}

void FilePicker::draw() noexcept {
	if (!m_show) {
		return;
	}
	auto constexpr popupSz = ImVec2{450.f, 0};
	ig::IDStackItem const idStackItem(m_title.c_str());
	if (ig::BeginPopup(m_sctx.tctx, m_title.c_str(), m_show, popupSz)) {
		auto const&list = m_sctx.project->fileList(m_fileExt);
		size_t selIdx{};
		ig::ComboBox(m_title.c_str(), list, selIdx);
		if (ig::PopupControlsOkCancel(popupSz.x, m_show) == ig::PopupResponse::OK) {
			filePicked.emit(list[selIdx]);
		}
		ImGui::EndPopup();
	}
}

void FilePicker::show() noexcept {
	m_show = true;
}

}
