#include "PngReader.h"
#include "BinaryStream.h"

#include "Image.h"

#include <iostream>
#include <sstream>

PngReader::~PngReader()
{

}

void PngReader::setPath(const std::string& path)
{
	mPath = path;
}

bool PngReader::checkSignature()
{
	const int highBitCheck = 0x89;
	const auto firstPos = mFile->GetInHandle()->get();
	if (firstPos != highBitCheck)
	{
		return false;
	}

	std::string fileType;
	BinaryStream::getNextString(mFile->GetInHandle(), fileType, 3);
	if (fileType != "PNG")
	{
		return false;
	}

	std::vector<char> sequence{13, 10, 26, 10};
	for (auto c : sequence)
	{
		if (mFile->GetInHandle()->get() != c)
		{
			return false;
		}
	}

	mCurrentOffset += 8;
	return true;
}

bool PngReader::readChunk()
{
	unsigned length = *BinaryStream::getNextDWord(mFile->GetInHandle());

	std::string chunkType;
	BinaryStream::getNextString(mFile->GetInHandle(), chunkType, 4);
	mCurrentOffset += 8;

	std::cout << "Got chunk with type: " << chunkType << " and length: " << length << std::endl;
	bool lastChunk = false;
	if (chunkType == "IHDR")
	{
		parseHeader();
	}
	else if(chunkType == "IEND")
	{
		lastChunk = true;
	}
	else
	{
		for(unsigned idx=0;idx<length;idx++)
		{
			mFile->GetInHandle()->get();
		}
	}

	unsigned crcCheck = *BinaryStream::getNextDWord(mFile->GetInHandle());

	mCurrentOffset += 4;
	return !lastChunk;
}

void PngReader::parseHeader()
{
	mIHDRChunk.width = *BinaryStream::getNextDWord(mFile->GetInHandle());
	mIHDRChunk.height = *BinaryStream::getNextDWord(mFile->GetInHandle());
	mIHDRChunk.bitDepth = mFile->GetInHandle()->get();
	mIHDRChunk.colorType = mFile->GetInHandle()->get();
	mIHDRChunk.compressionMethod = mFile->GetInHandle()->get();
	mIHDRChunk.filterMethod = mFile->GetInHandle()->get();
	mIHDRChunk.interlaceMethod = mFile->GetInHandle()->get();

	mCurrentOffset += 13;

	logHeader();
}

void PngReader::logHeader()
{
    std::stringstream sstr;
    sstr << "IHDR\n";
    sstr << "width: " << mIHDRChunk.width << "\n";
    sstr << "height: " << mIHDRChunk.height << "\n";
    sstr << "bitDepth: " << (int)mIHDRChunk.bitDepth << "\n";
    sstr << "colorType: " << (int)mIHDRChunk.colorType << "\n";
    sstr << "compressionMethod: " << (int)mIHDRChunk.compressionMethod << "\n";
    sstr << "filterMethod: " << (int)mIHDRChunk.filterMethod << "\n";
    sstr << "interlaceMethod: " << (int)mIHDRChunk.interlaceMethod << "\n";

    sstr << "************\n";
    std::cout << sstr.str() << std::endl;
}

std::unique_ptr<Image> PngReader::read()
{
	auto image = std::make_unique<Image>(5, 5);

    mFile = std::make_unique<File>(mPath);
    mFile->Open(true);

    if (!checkSignature())
    {
    	std::cout << "Signature check failed" << std::endl;
    	return image;
    }

    while(readChunk())
    {

    }

	return std::move(image);
}
