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

#include <ox/clargs/clargs.hpp>
#include <ox/std/trace.hpp>

#include <studio/project.hpp>

#include "change-format.hpp"

namespace studio {

static ox::Error convertFile(
	ox::FileSystem &fs,
	ox::TypeStore &ts,
	ox::StringViewCR path,
	ox::ClawFormat const fmt) noexcept {
	OX_REQUIRE_M(buff, fs.read(path).reoriginate(1, "unable to read file"));
	OX_REQUIRE(uuid, keel::readUuidHeader(buff));
	OX_REQUIRE(obj, keel::readAsset(ts, buff).reoriginate(1, "unable to parse file"));
	buff.clear();
	ox::BufferWriter writer{&buff};
	OX_RETURN_ERROR(keel::writeUuidHeader(writer, uuid));
	OX_RETURN_ERROR(ox::writeClaw(obj, writer, fmt));
	if (fmt == ox::ClawFormat::Organic) {
		*buff.back().value = '\n';
	}
	OX_RETURN_ERROR(fs.write(path, buff).reoriginate(1, "unable to write file"));
	return {};
}

static void printUsage() noexcept {
	oxErr("usage: change-format {mc,oc} [files...]\n");
}

[[nodiscard]]
static constexpr ox::Result<ox::ClawFormat> getFmt(ox::StringViewCR fmtStr) noexcept {
	if (caseInsensitiveStrCmp(fmtStr, "mc") == 0) {
		return ox::ClawFormat::Metal;
	} else if (caseInsensitiveStrCmp(fmtStr, "oc") == 0) {
		return ox::ClawFormat::Organic;
	}
	return ox::Error{1, "invalid format"};
}

ox::Error cmdChangeFormat(Project &project, ox::SpanView<ox::CString> const args) noexcept {
	if (args.size() < 2) {
		printUsage();
		return ox::Error{1, "invalid input"};
	}
	auto const [fmt, fmtErr] = getFmt(args[0]);
	if (fmtErr) {
		printUsage();
	}
	auto &fs = project.romFs();
	auto &ts = project.typeStore();
	for (auto const &file : args + 1) {
		auto const err = convertFile(fs, ts, file, fmt);
		if (err) {
			oxErrf("Failed to convert {}: {}\n", file, err.msg);
		}
	}
	return {};
}

}
