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

#pragma once

#include <ox/model/def.hpp>

#include <nostalgia/core/gfx.hpp>
#include <nostalgia/geo/vec.hpp>
#include <nostalgia/glutils/glutils.hpp>
#include <nostalgia/studio/studio.hpp>

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

namespace nostalgia::core {

enum class TileSheetTool: int {
	Select,
	Draw,
	Fill,
};

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

class TileSheetEditorView: public ox::SignalHandler {

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

	public:
		TileSheetEditorView(Context *ctx, const ox::String &path);

		~TileSheetEditorView() override = default;

		void draw() noexcept;

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

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

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

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

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

		void releaseMouseButton() noexcept;

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

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

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

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

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

		[[nodiscard]]
		constexpr const Palette *pal() const 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;

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

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

};

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

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

constexpr const Palette *TileSheetEditorView::pal() const noexcept {
	return m_model.pal();
}

}
