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

#include <studio/context.hpp>

namespace studio {

void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept {
	ox::String path = std::move(filePath);
	if (keel::isUuidUrl(path)) {
		auto const [p, err] = keel::uuidUrlToPath(keelCtx(ctx), path);
		if (err) {
			return;
		}
		path = p;
	}
	auto constexpr defaultVal =
		ox::MaxValue<ox::remove_reference_t<decltype(*ctx.navIdx)>>;
	ctx.navStack.resize(ctx.navIdx.or_value(defaultVal) + 1);
	ctx.navStack.emplace_back(ox::String{path}, ox::String{navArgs.view()});
	try {
		ctx.navCallback(std::move(path), std::move(navArgs));
	} catch (std::exception const &e) {
		oxErrf("Nav error: {}", e.what());
		oxAssert(false, "Nav error");
	}
}

void navigateBack(Context &ctx) noexcept {
	if (!ctx.navIdx) {
		return;
	}
	auto &navIdx = *ctx.navIdx;
	while (navIdx && navIdx < ctx.navStack.size()) {
		--navIdx;
		auto const &n = ctx.navStack[navIdx];
		// check for invalid entry
		if (!ctx.project->exists(n.filePath)) {
			// remove the invalid entry, then reset and retry
			auto const err = ctx.navStack.erase(navIdx);
			if (err.error) {
				return;
			}
			continue;
		}
		// entry is valid, do the navigation
		try {
			ctx.navCallback(n.filePath, n.navArgs);
		} catch (std::exception const &e) {
			oxAssert(ctx.navCallback != nullptr, "navCallback is null");
			oxErrf("navigateForward failed: {}", e.what());
		}
		break;
	}
}

void navigateForward(Context &ctx) noexcept {
	if (!ctx.navIdx) {
		ctx.navIdx.emplace(0u);
	}
	auto &navIdx = *ctx.navIdx;
	auto const nextIdx = navIdx + 1;
	while (nextIdx < ctx.navStack.size()) {
		auto const &n = ctx.navStack[nextIdx];
		if (!ctx.project->exists(n.filePath)) {
			std::ignore = ctx.navStack.erase(nextIdx);
			continue;
		}
		try {
			ctx.navCallback(n.filePath, n.navArgs);
		} catch (std::exception const &e) {
			oxAssert(ctx.navCallback != nullptr, "navCallback is null");
			oxErrf("navigateForward failed: {}", e.what());
		}
		++navIdx;
		break;
	}
}

}