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

#include <ox/model/model.hpp>

#include <keel/asset.hpp>
#include <keel/module.hpp>

#include <nostalgia/core/palette.hpp>
#include <nostalgia/core/tilesheet.hpp>

#include "typeconv.hpp"

namespace nostalgia::core {

class KeelModule: public keel::Module {
	private:
		NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter;
		PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter;
		TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
		TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
		TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
		TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;

	public:
		[[nodiscard]]
		ox::String id() const noexcept override {
			return ox::String("net.drinkingtea.nostalgia.core");
		}

		[[nodiscard]]
		ox::Vector<keel::TypeDescGenerator> types() const noexcept final {
			return {
				keel::generateTypeDesc<TileSheetV1>,
				keel::generateTypeDesc<TileSheetV2>,
				keel::generateTypeDesc<TileSheetV3>,
				keel::generateTypeDesc<TileSheetV4>,
				keel::generateTypeDesc<CompactTileSheet>,
				keel::generateTypeDesc<PaletteV1>,
				keel::generateTypeDesc<PaletteV2>,
			};
		}

		[[nodiscard]]
		ox::Vector<keel::BaseConverter const*> converters() const noexcept final {
			return {
				&m_nostalgiaPaletteToPaletteV1Converter,
				&m_paletteV1ToPaletteV2Converter,
				&m_tileSheetV1ToTileSheetV2Converter,
				&m_tileSheetV2ToTileSheetV3Converter,
				&m_tileSheetV3ToTileSheetV4Converter,
				&m_tileSheetToCompactTileSheetConverter,
			};
		}

		[[nodiscard]]
		ox::Vector<keel::PackTransform> packTransforms() const noexcept final {
			return {
				// convert tilesheets to CompactTileSheets
				[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
					oxRequire(hdr, keel::readAssetHeader(buff));
					auto const typeId = ox::buildTypeId(
							hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
					if (typeId == ox::buildTypeId<TileSheetV1>() ||
					    typeId == ox::buildTypeId<TileSheetV2>() ||
					    typeId == ox::buildTypeId<TileSheetV3>() ||
					    typeId == ox::buildTypeId<TileSheetV4>()) {
						oxReturnError(keel::convertBuffToBuff<core::CompactTileSheet>(
								ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
					}
					return {};
				},
				[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
					oxRequire(hdr, keel::readAssetHeader(buff));
					auto const typeId = ox::buildTypeId(
							hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
					if (typeId == ox::buildTypeId<NostalgiaPalette>() ||
					    typeId == ox::buildTypeId<PaletteV1>()) {
						oxReturnError(keel::convertBuffToBuff<core::Palette>(
								ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
					}
					return {};
				},
			};
		}
};

static const KeelModule mod;
const keel::Module *keelModule() noexcept {
	return &mod;
}

}
