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

#include "inserttilescommand.hpp"

namespace nostalgia::core {

core::InsertTilesCommand::InsertTilesCommand(
		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_insertPos = tileIdx * bytesPerTile;
	m_insertCnt = tileCnt * bytesPerTile;
	m_deletedPixels.resize(m_insertCnt);
	// copy pixels to be erased
	{
		auto &s = m_img.getSubSheet(m_idx);
		auto &p = s.pixels;
		auto dst = m_deletedPixels.data();
		auto src = p.data() + p.size() - m_insertCnt;
		const auto sz = m_insertCnt * sizeof(decltype(p[0]));
		ox_memcpy(dst, src, sz);
	}
}

void InsertTilesCommand::redo() noexcept {
	auto &s = m_img.getSubSheet(m_idx);
	auto &p = s.pixels;
	auto dstPos = m_insertPos + m_insertCnt;
	const auto dst = p.data() + dstPos;
	const auto src = p.data() + m_insertPos;
	ox_memmove(dst, src, p.size() - dstPos);
	ox_memset(src, 0, m_insertCnt * sizeof(decltype(p[0])));
}

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

int InsertTilesCommand::commandId() const noexcept {
	return static_cast<int>(CommandId::InsertTile);
}

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

}
