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

#include <studio/undostack.hpp>

namespace studio {

ox::Error UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
	m_stack.resize(m_stackIdx);
	OX_RETURN_ERROR(cmd->redo());
	redoTriggered.emit(cmd.get());
	changeTriggered.emit(cmd.get());
	if (m_stack.empty() || !(*m_stack.back().value)->mergeWith(*cmd)) {
		m_stack.emplace_back(std::move(cmd));
		++m_stackIdx;
	}
	if ((*m_stack.back().unwrap())->isObsolete()) {
		m_stack.pop_back();
		--m_stackIdx;
	}
	return {};
}

ox::Error UndoStack::redo() noexcept {
	while (m_stackIdx < m_stack.size()) {
		auto const &c = m_stack[m_stackIdx];
		++m_stackIdx;
		if (!c->isObsolete()) {
			OX_RETURN_ERROR(c->redo());
			redoTriggered.emit(c.get());
			changeTriggered.emit(c.get());
			break;
		}
	}
	return {};
}

ox::Error UndoStack::undo() noexcept {
	while (m_stackIdx) {
		--m_stackIdx;
		auto const &c = m_stack[m_stackIdx];
		if (!c->isObsolete()) {
			OX_RETURN_ERROR(c->undo());
			undoTriggered.emit(c.get());
			changeTriggered.emit(c.get());
			break;
		}
	}
	return {};
}

}
