#include <lzma.h>
#include <iostream>
#include "diff.hpp"
#include "ceedee_tex.h"

#include "CdTex.hpp"
#include "CdType.hpp"

namespace Li::Gui::DvdSpin {
	CdTex::CdTex() {
		this->uncompressedTextureSz = ceedeeImgUncompressedSz;
		this->uncompressedTexture = new std::byte[this->uncompressedTextureSz];
		this->SetUnknownTexture();
	}

	void CdTex::applyDiff(uint32_t numChanges, ImgDiff* changesList) {
		uint32_t* uncompressedTextureRGBA = (uint32_t*)this->uncompressedTexture;
		for (unsigned int i = 0; i < numChanges; i++) {
			ImgDiff curChange = changesList[i];
			uncompressedTextureRGBA[curChange.Location] = curChange.NewColor;
		}
	}

	void CdTex::SetCdTexture() {
		if (this->currentCdType == CdType::COMPACT_DISC) return;
		if (this->currentCdType != CdType::UNKNOWN_DISC) this->SetUnknownTexture();
		this->applyDiff(ceedeeCdDiffSz, ceedeeCdDiff);
		this->currentCdType = CdType::COMPACT_DISC;
	}

	void CdTex::SetDvdTexture() {
		if (this->currentCdType == CdType::DIGITAL_VERSITLE_DISC) return;
		if (this->currentCdType != CdType::UNKNOWN_DISC) this->SetUnknownTexture();
		this->applyDiff(ceedeeDvdDiffSz, ceedeeDvdDiff);
		this->currentCdType = CdType::DIGITAL_VERSITLE_DISC;
	}
	void CdTex::SetHdDvdTexture() {
		if (this->currentCdType == CdType::HIGH_DEFINITION_DIGITAL_VERSITLE_DISC) return;
		if (this->currentCdType != CdType::UNKNOWN_DISC) this->SetUnknownTexture();
		this->applyDiff(ceedeeHdDvdDiffSz, ceedeeHdDvdDiff);
		this->currentCdType = CdType::HIGH_DEFINITION_DIGITAL_VERSITLE_DISC;
	}

	void CdTex::SetBdTexture() {
		if (this->currentCdType == CdType::BLU_RAY) return;
		if (this->currentCdType != CdType::UNKNOWN_DISC) this->SetUnknownTexture();
		this->applyDiff(ceedeeBluRayDiffSz, ceedeeBluRayDiff);
		this->currentCdType = CdType::BLU_RAY;
	}

	void CdTex::SetUnknownTexture() {
		uint32_t compressedSize = ceedeeImgCompressedDataSz;
		lzma2decompress((unsigned char*)&ceedeeImgCompressedData, &compressedSize, (unsigned char*)this->uncompressedTexture, &this->uncompressedTextureSz);
		this->currentCdType = CdType::UNKNOWN_DISC;
	}

	uint32_t CdTex::Width() {
		return ceedeeImgWidth;
	}
	
	uint32_t CdTex::Height() {
		return ceedeeImgHeight;
	}

	uint32_t CdTex::Channels() {
		return ceedeeImgChannels;
	}

	uint32_t CdTex::Pitch() {
		return (this->Width() * this->Channels());
	}

	CdType CdTex::CurrentCdType() {
		return this->currentCdType;
	}

	std::byte* CdTex::CurrentTexture() {
		return this->uncompressedTexture;
	}

	CdTex::~CdTex() {
		this->currentCdType = CdType::UNKNOWN_DISC;
		delete this->uncompressedTexture;
	}
}
