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

#include "typeconv.hpp"

namespace nostalgia::gfx {

ox::Error convertNostalgiaPaletteToPaletteV1(
		keel::Context&,
		NostalgiaPalette &src,
		PaletteV1 &dst) noexcept {
	dst.colors = std::move(src.colors);
	return {};
}

ox::Error convertPaletteV1ToPaletteV2(
		keel::Context&,
		PaletteV1 &src,
		PaletteV2 &dst) noexcept {
	dst.pages.emplace_back(std::move(src.colors));
	return {};
}

ox::Error convertPaletteV2ToPaletteV3(
		keel::Context&,
		PaletteV2 &src,
		PaletteV3 &dst) noexcept {
	dst.pages = std::move(src.pages);
	if (!dst.pages.empty()) {
		dst.colorInfo.reserve(dst.pages[0].size());
		for (size_t i = 0; i < dst.pages[0].size(); ++i) {
			dst.colorInfo.emplace_back(ox::sfmt("Color {}", i + 1));
		}
	}
	return {};
}

ox::Error convertPaletteV3ToPaletteV4(
		keel::Context&,
		PaletteV3 &src,
		PaletteV4 &dst) noexcept {
	dst.pages.reserve(src.pages.size());
	for (auto i = 1; auto &page : src.pages) {
		dst.pages.emplace_back(ox::sfmt("Page {}", i), std::move(page));
		++i;
	}
	dst.colorNames.reserve(src.colorInfo.size());
	for (auto &ci : src.colorInfo) {
		dst.colorNames.emplace_back(std::move(ci.name));
	}
	return {};
}

ox::Error convertPaletteV4ToPaletteV5(
		keel::Context&,
		PaletteV4 &src,
		PaletteV5 &dst) noexcept {
	dst.colorNames = std::move(src.colorNames);
	dst.pages.reserve(src.pages.size());
	for (auto &s : src.pages) {
		ox::Vector<PaletteColorV2> colors;
		colors.reserve(s.colors.size());
		for (auto const &c : s.colors) {
			colors.emplace_back(c.r, c.g, c.b, c.a);
		}
		dst.pages.emplace_back(PalettePageV2{
			std::move(s.name),
			std::move(colors),
		});
	}
	return {};
}

ox::Error convertPaletteToCompactPalette(
		keel::Context&,
		Palette &src,
		CompactPalette &dst) noexcept {
	dst.pages.reserve(src.pages.size());
	for (auto &page : src.pages) {
		auto &p = dst.pages.emplace_back();
		for (auto const c : page.colors) {
			p.emplace_back(c);
		}
	}
	return {};
}

ox::Error convertTileSheetV1ToTileSheetV2(
		keel::Context&,
		TileSheetV1 &src,
		TileSheetV2 &dst) noexcept {
	dst.bpp              = src.bpp;
	dst.defaultPalette   = std::move(src.defaultPalette);
	dst.subsheet.name    = "Root";
	dst.subsheet.rows    = src.rows;
	dst.subsheet.columns = src.columns;
	dst.subsheet.pixels  = std::move(src.pixels);
	return {};
}

static void convertSubsheet(
		TileSheetV2::SubSheet &src,
		TileSheetV3::SubSheet &dst,
		SubSheetId &idIt) noexcept {
	dst.id      = idIt;
	dst.name    = std::move(src.name);
	dst.columns = src.columns;
	dst.rows    = src.rows;
	dst.pixels  = std::move(src.pixels);
	++idIt;
	dst.subsheets.reserveResize(src.subsheets.size());
	for (size_t i{}; i < src.subsheets.size(); ++i) {
		convertSubsheet(src.subsheets[i], dst.subsheets[i], idIt);
	}
}

ox::Error convertTileSheetV2ToTileSheetV3(
		keel::Context&,
		TileSheetV2 &src,
		TileSheetV3 &dst) noexcept {
	dst.bpp            = src.bpp;
	dst.defaultPalette = std::move(src.defaultPalette);
	convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
	return {};
}


static void convertSubsheet(
		TileSheetV3::SubSheet &src,
		TileSheetV4::SubSheet &dst,
		SubSheetId &idIt) noexcept {
	dst.id      = idIt;
	dst.name    = std::move(src.name);
	dst.columns = src.columns;
	dst.rows    = src.rows;
	dst.pixels  = std::move(src.pixels);
	++idIt;
	dst.subsheets.reserveResize(src.subsheets.size());
	for (size_t i{}; i < src.subsheets.size(); ++i) {
		convertSubsheet(src.subsheets[i], dst.subsheets[i], idIt);
	}
}

ox::Error convertTileSheetV3ToTileSheetV4(
		keel::Context&,
		TileSheetV3 &src,
		TileSheetV4 &dst) noexcept {
	dst.bpp            = src.bpp;
	dst.idIt           = src.idIt;
	dst.defaultPalette = std::move(src.defaultPalette);
	convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
	return {};
}


static void convertSubsheet(
		int const bpp,
		TileSheetV4::SubSheet &src,
		TileSheetV5::SubSheet &dst) noexcept {
	dst.id      = src.id;
	dst.name    = std::move(src.name);
	dst.columns = src.columns;
	dst.rows    = src.rows;
	if (bpp == 4) {
		dst.pixels.reserve(2 * src.pixels.size());
		dst.pixels.resize(0);
		for (auto const p : src.pixels) {
			dst.pixels.emplace_back(static_cast<uint8_t>(p & 0xf));
			dst.pixels.emplace_back(static_cast<uint8_t>(p >> 4));
		}
		oxAssert(dst.pixels.size() == src.pixels.size() * 2, "mismatch");
	} else {
		dst.pixels = std::move(src.pixels);
	}
	dst.subsheets.reserveResize(src.subsheets.size());
	for (size_t i{}; i < src.subsheets.size(); ++i) {
		convertSubsheet(bpp, src.subsheets[i], dst.subsheets[i]);
	}
}

ox::Error convertTileSheetV4ToTileSheetV5(
		keel::Context&,
		TileSheetV4 &src,
		TileSheetV5 &dst) noexcept {
	dst.bpp  = src.bpp;
	dst.idIt = src.idIt;
	OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette));
	convertSubsheet(dst.bpp, src.subsheet, dst.subsheet);
	return {};
}


ox::Error convertTileSheetToCompactTileSheet(
		keel::Context&,
		TileSheet &src,
		CompactTileSheet &dst) noexcept {
	dst.bpp            = src.bpp;
	dst.defaultPalette = ox::FileAddress{src.defaultPalette};
	dst.pixels         = pixels(src);
	return {};
}

}
