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

#pragma once

#include <ox/std/vec.hpp>
#include <ox/model/def.hpp>

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

#include <nostalgia/gfx/gfx.hpp>

#include "tilesheeteditormodel.hpp"
#include "tilesheetpixelgrid.hpp"
#include "tilesheetpixels.hpp"

namespace nostalgia::gfx {

enum class TileSheetTool {
	None,
	Select,
	Draw,
	Fill,
	Line,
};

[[nodiscard]]
constexpr auto toString(TileSheetTool t) noexcept {
	switch (t) {
		case TileSheetTool::Select:
			return "Select";
		case TileSheetTool::Draw:
			return "Draw";
		case TileSheetTool::Fill:
			return "Fill";
		case TileSheetTool::Line:
			return "Line";
		case TileSheetTool::None:
			return "None";
	}
	return "";
}

class TileSheetEditorView: public ox::SignalHandler {

	private:
		TileSheetEditorModel m_model;
		TileSheetGrid m_pixelGridDrawer;
		TileSheetPixels m_pixelsDrawer;
		ox::Vec2 m_viewSize;
		float m_pixelSizeMod = 1;
		bool m_updated = false;
		ox::Vec2 m_scrollOffset;
		std::size_t m_palIdx = 0;

	public:
		TileSheetEditorView(studio::Context &sctx, ox::StringViewCR path, studio::UndoStack &undoStack);

		~TileSheetEditorView() override = default;

		void draw() noexcept;

		void insertTile(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void deleteTile(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void clickDraw(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void clickLine(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void clickSelect(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void clickFill(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) noexcept;

		void releaseMouseButton(TileSheetTool tool) noexcept;

		void scrollV(ox::Vec2 const &paneSz, float wheel, bool zoomMod) noexcept;

		void scrollH(ox::Vec2 const &paneSz, float wheel) noexcept;

		void resizeView(ox::Vec2 const &sz) noexcept;

		[[nodiscard]]
		constexpr TileSheet const &img() const noexcept;

		[[nodiscard]]
		constexpr TileSheet &img() noexcept;

		[[nodiscard]]
		constexpr auto &model() noexcept {
			return m_model;
		}

		[[nodiscard]]
		constexpr auto &model() const noexcept {
			return m_model;
		}

		constexpr auto setPalIdx(auto palIdx) noexcept {
			m_palIdx = palIdx;
		}

		[[nodiscard]]
		constexpr auto palIdx() const noexcept {
			return m_palIdx;
		}

		[[nodiscard]]
		bool updated() const noexcept;

		ox::Error markUpdated() noexcept;

		void ackUpdate() noexcept;

	private:
		void initView() noexcept;

		ox::Point clickPoint(ox::Vec2 const &paneSize, ox::Vec2 const &clickPos) const noexcept;

		ox::Error setActiveSubsheet(TileSheet::SubSheetIdx const &idx) noexcept;

};

constexpr TileSheet const &TileSheetEditorView::img() const noexcept {
	return m_model.img();
}

constexpr TileSheet &TileSheetEditorView::img() noexcept {
	return m_model.img();
}

}
