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

#include "deletetilescommand.hpp"

namespace nostalgia::core {

core::DeleteTilesCommand::DeleteTilesCommand(
		TileSheet &img,
		TileSheet::SubSheetIdx idx,
		std::size_t tileIdx,
		std::size_t tileCnt) noexcept:
		m_img(img),
		m_idx(std::move(idx)) {
	const unsigned bytesPerTile = m_img.bpp == 4 ? PixelsPerTile / 2 : PixelsPerTile;
	m_deletePos = tileIdx * bytesPerTile;
	m_deleteSz = tileCnt * bytesPerTile;
	m_deletedPixels.resize(m_deleteSz);
	// copy pixels to be erased
	{
		auto &s = getSubSheet(m_img, m_idx);
		auto &p = s.pixels;
		auto dst = m_deletedPixels.data();
		auto src = p.data() + m_deletePos;
		const auto sz = m_deleteSz * sizeof(decltype(p[0]));
		ox_memcpy(dst, src, sz);
	}
}

void core::DeleteTilesCommand::redo() noexcept {
	auto &s = getSubSheet(m_img, m_idx);
	auto &p = s.pixels;
	auto srcPos = m_deletePos + m_deleteSz;
	const auto src = p.data() + srcPos;
	const auto dst1 = p.data() + m_deletePos;
	const auto dst2 = p.data() + (p.size() - m_deleteSz);
	ox_memmove(dst1, src, p.size() - srcPos);
	ox_memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0])));
}

void DeleteTilesCommand::undo() noexcept {
	auto &s = getSubSheet(m_img, m_idx);
	auto &p = s.pixels;
	const auto src = p.data() + m_deletePos;
	const auto dst1 = p.data() + m_deletePos + m_deleteSz;
	const auto dst2 = src;
	const auto sz = p.size() - m_deletePos - m_deleteSz;
	ox_memmove(dst1, src, sz);
	ox_memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
}

int DeleteTilesCommand::commandId() const noexcept {
	return static_cast<int>(CommandId::DeleteTile);
}

TileSheet::SubSheetIdx const&DeleteTilesCommand::subsheetIdx() const noexcept {
	return m_idx;
}

}
