/*
 * Copyright 2016 - 2023 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:
		NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter;
		TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
		TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetConverter;
		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<TileSheet>,
				keel::generateTypeDesc<CompactTileSheet>,
				keel::generateTypeDesc<Palette>,
			};
		}

		[[nodiscard]]
		ox::Vector<const keel::BaseConverter*> converters() const noexcept final {
			return {
				&m_nostalgiaPaletteToPaletteConverter,
				&m_tileSheetV1ToTileSheetV2Converter,
				&m_tileSheetV2ToTileSheetConverter,
				&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));
					const auto typeId = ox::buildTypeId(
							hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
					if (typeId == ox::buildTypeId<TileSheetV1>() ||
						 typeId == ox::buildTypeId<TileSheetV2>() ||
						 typeId == ox::buildTypeId<TileSheet>()) {
						oxReturnError(keel::convertBuffToBuff<core::CompactTileSheet>(
								ctx, buff, ox::ClawFormat::Metal).moveTo(&buff));
					}
					return {};
				},
			};
		}
};

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

}
