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

#include <algorithm>

#include <ox/std/string.hpp>

#include <studio/editor.hpp>

namespace studio {

ox::CStringView BaseEditor::itemDisplayName() const noexcept {
	return itemPath();
}

void BaseEditor::cut() {
}

void BaseEditor::copy() {
}

void BaseEditor::paste() {
}

bool BaseEditor::acceptsClipboardPayload() const noexcept {
	return {};
}

void BaseEditor::exportFile() {
}

void BaseEditor::keyStateChanged(turbine::Key, bool) {
}

void BaseEditor::onActivated() noexcept {
}

void BaseEditor::close() const {
	this->closed.emit(itemPath());
}

void BaseEditor::save() noexcept {
	auto const err = saveItem();
	if (!err) {
		setUnsavedChanges(false);
	} else {
		if constexpr(ox::defines::Debug) {
			oxErrorf("Could not save file {}: {} ({}:{})", itemPath(), toStr(err), err.src.file_name(), err.src.line());
		} else {
			oxErrorf("Could not save file {}: {}", itemPath(), toStr(err));
		}
	}
}

void BaseEditor::setUnsavedChanges(bool uc) {
	m_unsavedChanges = uc;
	unsavedChangesChanged.emit(uc);
}

bool BaseEditor::unsavedChanges() const noexcept {
	return m_unsavedChanges;
}

void BaseEditor::setExportable(bool exportable) noexcept {
	m_exportable = exportable;
	exportableChanged.emit(exportable);
}

bool BaseEditor::exportable() const noexcept {
	return m_exportable;
}

void BaseEditor::setCutEnabled(bool v) {
	if (m_cutEnabled != v) {
		m_cutEnabled = v;
		cutEnabledChanged.emit(v);
	}
}

bool BaseEditor::cutEnabled() const noexcept {
	return m_cutEnabled;
}

void BaseEditor::setCopyEnabled(bool v) {
	if (m_copyEnabled != v) {
		m_copyEnabled = v;
		copyEnabledChanged.emit(v);
	}
}

bool BaseEditor::copyEnabled() const noexcept {
	return m_copyEnabled;
}

void BaseEditor::setPasteEnabled(bool v) {
	if (m_pasteEnabled != v) {
		m_pasteEnabled = v;
		pasteEnabledChanged.emit(v);
	}
}

bool BaseEditor::pasteEnabled() const noexcept {
	return m_pasteEnabled && acceptsClipboardPayload();
}

ox::Error BaseEditor::saveItem() noexcept {
	return {};
}

UndoStack *BaseEditor::undoStack() noexcept {
	return nullptr;
}

void BaseEditor::navigateTo(ox::StringViewCR) noexcept {}


Editor::Editor(Context &ctx, ox::StringParam itemPath) noexcept:
		m_itemPath(std::move(itemPath)),
		m_itemName(m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1)) {
	m_undoStack.changeTriggered.connect(this, &Editor::markUnsavedChanges);
	ctx.project->fileMoved.connect(this, &Editor::handleRename);
}

[[nodiscard]]
ox::CStringView Editor::itemPath() const noexcept {
	return m_itemPath;
}

[[nodiscard]]
ox::CStringView Editor::itemDisplayName() const noexcept {
	return m_itemName;
}

ox::Error Editor::pushCommand(ox::UPtr<UndoCommand> &&cmd) noexcept {
	return m_undoStack.push(std::move(cmd));
}

UndoStack *Editor::undoStack() noexcept {
	return &m_undoStack;
}

ox::Error Editor::markUnsavedChanges(UndoCommand const*) noexcept {
	setUnsavedChanges(true);
	return {};
}

ox::Error Editor::handleRename(ox::StringViewCR oldPath, ox::StringViewCR newPath, ox::UUID const&) noexcept {
	if (m_itemPath == oldPath) {
		m_itemPath = newPath;
		m_itemName = m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1);
	}
	return {};
}

}
