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

#pragma once

#include <ox/claw/claw.hpp>
#include <ox/event/signal.hpp>
#include <ox/std/string.hpp>

#include <studio/filetreemodel.hpp>
#include <studio/itemmaker.hpp>
#include <studio/popup.hpp>

namespace studio {

class NewMenu final: public Popup {
	public:
		enum class Stage {
			Closed,
			Opening,
			NewItemType,
			NewItemTransitioningToPath,
			NewItemPath,
			NewItemTemplate,
		};

		// emits path parameter
		ox::Signal<ox::Error(ox::StringView)> finished;

	private:
		Stage m_stage = Stage::Closed;
		ox::Vector<Stage, 2> m_prev;
		keel::Context &m_kctx;
		ox::String m_typeName;
		ox::IString<255> m_itemName;
		bool m_useDefaultPath{};
		ox::Vector<ox::UPtr<ItemMaker>> m_types;
		FileExplorer m_explorer{m_kctx};
		size_t m_selectedType = 0;
		size_t m_selectedTemplate = 0;
		bool m_open = false;

	public:
		NewMenu(keel::Context &kctx) noexcept;

		void openPath(ox::StringViewCR path) noexcept;

		void open() noexcept override;

		void close() noexcept override;

		[[nodiscard]]
		bool isOpen() const noexcept override;

		void draw(Context &sctx) noexcept override;

		template<typename T>
		void addItemType(
			ox::StringParam displayName,
			ox::StringParam parentDir,
			ox::StringParam fileExt,
			T itemTempl,
			ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;

		template<typename T>
		void addItemType(
			ox::StringParam displayName,
			ox::StringParam parentDir,
			ox::StringParam fileExt,
			ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;

		void addItemMaker(ox::UPtr<ItemMaker> &&im) noexcept;

		void installItemTemplate(ox::UPtr<ItemTemplate> &&tmplt) noexcept;

	private:
		void drawNewItemType(Context const &sctx) noexcept;

		void drawNewItemPath(Context &sctx) noexcept;

		void drawNewItemTemplate(Context const &sctx) noexcept;

		void drawButtons(Stage next) noexcept;

		void drawFirstPageButtons(Stage next) noexcept;

		void drawLastPageButtons(Context &sctx) noexcept;

		void finish(Context &sctx) noexcept;

};

template<typename T>
void NewMenu::addItemType(
	ox::StringParam displayName,
	ox::StringParam parentDir,
	ox::StringParam fileExt,
	T itemTempl,
	ox::ClawFormat const pFmt) noexcept {
	m_types.emplace_back(ox::make<ItemMakerT<T>>(
		std::move(displayName),
		std::move(parentDir),
		std::move(fileExt),
		std::move(itemTempl),
		pFmt));
}

template<typename T>
void NewMenu::addItemType(
	ox::StringParam displayName,
	ox::StringParam parentDir,
	ox::StringParam fileExt,
	ox::ClawFormat const pFmt) noexcept {
	m_types.emplace_back(ox::make<ItemMakerT<T>>(
		std::move(displayName),
		std::move(parentDir),
		std::move(fileExt),
		pFmt));
}

}
