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

#pragma once

#include <ox/std/smallmap.hpp>

#include <studio/filepickerpopup.hpp>
#include <studio/studio.hpp>

#include <jasper/world/consts.hpp>

#include "worldeditorview.hpp"

namespace jasper::world {

class WorldEditorImGui: public studio::Editor {

	private:
		studio::SelectionTracker m_selTracker;
		ox::Optional<studio::Selection> m_selection;
		uint8_t m_activeLayer{};
		studio::Context &m_sctx;
		studio::FilePickerPopup m_objSetPicker;
		WorldDoc m_doc;
		struct ObjSetRef {
			ox::String name;
			uint64_t id{};
			keel::AssetRef<WorldObjectSet> set;
			ObjSetRef(ox::String pName, uint64_t pId, keel::AssetRef<WorldObjectSet> pSet):
				name(std::move(pName)),
				id(pId),
				set(std::move(pSet)) {}
			constexpr ObjSetRef() = default;
		};
		ox::Vector<ObjSetRef> m_objSets;
		ox::SmallMap<ox::UUID, bool> m_dependencies;
		WorldStatic m_worldStatic;
		WorldStaticLoader m_loader{keelCtx(m_sctx), m_worldStatic, m_doc};
		WorldEditorView m_view{m_sctx, m_worldStatic};
		struct {
			ox::UUIDStr selectedObjSet;
		} m_objMgr;
		struct {
			bool show{};
			int columns{};
			int rows{};
		} m_sizeEditor;

	public:
		WorldEditorImGui(studio::Context &sctx, ox::StringParam path);

		void draw(studio::Context&) noexcept final;

		void onActivated() noexcept override;

	protected:
		void copy() override;

		void cut() noexcept override;

		void paste() override;

		bool acceptsClipboardPayload() const noexcept override;

		ox::Error saveItem() noexcept final;

	private:
		void drawObjSelector() noexcept;

		void drawPropEditor() noexcept;

		void drawMenu() noexcept;

		void drawResources() noexcept;

		void drawWorldView() noexcept;

		void handleMouseSelection(float fbPaneScale) noexcept;

		ox::Error handleDrop(float fbPaneScale) noexcept;

		ox::Error addObjSet(ox::StringViewCR path) noexcept;

		void rmObjSet() noexcept;

		// handles the updating of an object set in case it is one used by this world
		ox::Error handleDepUpdate(ox::StringViewCR path, ox::UUID const &) noexcept;

		ox::Error loadObjectSets() noexcept;

		[[nodiscard]]
		bool tileSelected(ox::Point const &pt) const noexcept;

		void clearSelection() noexcept;

		ox::Result<ox::UUID> assetId() const noexcept;

		ox::Error addDependency(ox::FileAddress const &fileAddr) noexcept;

		ox::Error handleUndoStackChange(studio::UndoCommand const*) noexcept;

		[[nodiscard]]
		constexpr bool popupOpen() const noexcept {
			return m_sizeEditor.show;
		}
};

}
