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

#include <keel/asset.hpp>

namespace keel {

ox::Result<ox::UUID> readUuidHeader(ox::BufferView const &buff) noexcept {
	if (buff.size() < K1HdrSz) [[unlikely]] {
		return ox::Error{1, "Insufficient data to contain complete Keel header"};
	}
	constexpr ox::StringView k1Hdr = "K1;";
	if (k1Hdr != ox::StringView{buff.data(), k1Hdr.bytes()}) [[unlikely]] {
		return ox::Error{2, "No Keel asset header data"};
	}
	return ox::UUID::fromString(ox::StringView(&buff[k1Hdr.bytes()], 36));
}

ox::Result<ox::UUID> regenerateUuidHeader(ox::Buffer &buff) noexcept {
	OX_RETURN_ERROR(readUuidHeader(buff));
	OX_REQUIRE(id, ox::UUID::generate());
	auto const str = id.toString();
	for (size_t i = 0; i < ox::UUIDStr::cap(); ++i) {
		buff[i + 3] = str[i];
	}
	return id;
}

ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::BufferView const &buff) noexcept {
	std::size_t offset = 0;
	if (!readUuidHeader(buff).error) {
		offset = K1HdrSz;
	}
	return ox::readClaw(ts, buff + offset);
}

ox::Result<ox::StringView> readAssetTypeId(ox::BufferView const &buff) noexcept {
	auto const err = readUuidHeader(buff).error;
	auto const offset = err ? 0u : K1HdrSz;
	if (offset >= buff.size()) [[unlikely]] {
		return ox::Error(1, "Buffer too small for expected data");
	}
	return ox::readClawTypeId(buff + offset);
}

ox::Result<AssetHdr> readAssetHeader(ox::BufferView const &buff) noexcept {
	ox::Result<AssetHdr> out;
	auto const err = readUuidHeader(buff).moveTo(out.value.uuid);
	auto const offset = err ? 0u : K1HdrSz;
	if (offset >= buff.size()) [[unlikely]] {
		return ox::Error(1, "Buffer too small for expected data");
	}
	OX_RETURN_ERROR(ox::readClawHeader(buff + offset).moveTo(out.value.clawHdr));
	return out;
}

}
