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

#include "paletteeditor.hpp"

namespace nostalgia::core {

AddPageCommand::AddPageCommand(Palette &pal) noexcept:
	m_pal(pal) {
}

int AddPageCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::AddPage);
}

void AddPageCommand::redo() noexcept {
	m_pal.pages.emplace_back();
}

void AddPageCommand::undo() noexcept {
	oxIgnoreError(m_pal.pages.erase(static_cast<std::size_t>(m_pal.pages.size() - 1)));
}


DuplicatePageCommand::DuplicatePageCommand(Palette &pal, size_t srcIdx, size_t dstIdx) noexcept:
		m_pal(pal),
		m_dstIdx(dstIdx) {
	auto const&src = m_pal.pages[srcIdx];
	m_page.reserve(src.size());
	for (auto const&s : src) {
		m_page.emplace_back(s);
	}
}

int DuplicatePageCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::DuplicatePage);
}

void DuplicatePageCommand::redo() noexcept {
	m_pal.pages.emplace(m_dstIdx, std::move(m_page));
}

void DuplicatePageCommand::undo() noexcept {
	m_page = std::move(m_pal.pages[m_dstIdx]);
	oxIgnoreError(m_pal.pages.erase(static_cast<std::size_t>(m_dstIdx)));
}

size_t DuplicatePageCommand::insertIdx() const noexcept {
	return m_dstIdx;
}


RemovePageCommand::RemovePageCommand(Palette &pal, size_t idx) noexcept:
	m_pal(pal),
	m_idx(idx) {
}

int RemovePageCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::RemovePage);
}

void RemovePageCommand::redo() noexcept {
	m_page = std::move(m_pal.pages[m_idx]);
	oxIgnoreError(m_pal.pages.erase(static_cast<std::size_t>(m_idx)));
}

void RemovePageCommand::undo() noexcept {
	m_pal.pages.insert(m_idx, std::move(m_page));
}


AddColorCommand::AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept {
	m_pal = pal;
	m_color = color;
	m_page = page;
	m_idx = idx;
}

int AddColorCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::AddColor);
}

void AddColorCommand::redo() noexcept {
	m_pal->pages[m_page].insert(static_cast<std::size_t>(m_idx), m_color);
}

void AddColorCommand::undo() noexcept {
	oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(m_idx)));
}


RemoveColorCommand::RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept {
	m_pal = pal;
	m_color = color;
	m_page = page;
	m_idx = idx;
}

int RemoveColorCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::RemoveColor);
}

void RemoveColorCommand::redo() noexcept {
	oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(m_idx)));
}

void RemoveColorCommand::undo() noexcept {
m_pal->pages[m_page].insert(static_cast<std::size_t>(m_idx), m_color);
}


UpdateColorCommand::UpdateColorCommand(
		Palette *pal,
		size_t page,
		int idx,
		Color16 oldColor,
		Color16 newColor) noexcept {
	m_pal = pal;
	m_page = page;
	m_idx = idx;
	m_oldColor = oldColor;
	m_newColor = newColor;
	//setObsolete(m_oldColor == m_newColor);
}

bool UpdateColorCommand::mergeWith(const UndoCommand *cmd) noexcept {
	if (cmd->commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) {
		return false;
	}
	auto ucCmd = static_cast<const UpdateColorCommand*>(cmd);
	if (m_idx != ucCmd->m_idx) {
		return false;
	}
	m_newColor = ucCmd->m_newColor;
	return true;
}

[[nodiscard]]
int UpdateColorCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::UpdateColor);
}

void UpdateColorCommand::redo() noexcept {
	m_pal->pages[m_page][static_cast<std::size_t>(m_idx)] = m_newColor;
}

void UpdateColorCommand::undo() noexcept {
	m_pal->pages[m_page][static_cast<std::size_t>(m_idx)] = m_oldColor;
}


MoveColorCommand::MoveColorCommand(Palette *pal, size_t page, std::size_t idx, int offset) noexcept {
	m_pal = pal;
	m_page = page;
	m_idx = idx;
	m_offset = offset;
}

int MoveColorCommand::commandId() const noexcept {
	return static_cast<int>(PaletteEditorCommandId::MoveColor);
}

void MoveColorCommand::redo() noexcept {
	moveColor(static_cast<int>(m_idx), m_offset);
}

void MoveColorCommand::undo() noexcept {
	moveColor(static_cast<int>(m_idx) + m_offset, -m_offset);
}

void MoveColorCommand::moveColor(int idx, int offset) noexcept {
	const auto c = m_pal->pages[m_page][static_cast<std::size_t>(idx)];
	oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(idx)));
	m_pal->pages[m_page].insert(static_cast<std::size_t>(idx + offset), c);
}

}