#include "PngHeader.h"

#include "ByteUtils.h"
#include "StringUtils.h"
#include "CyclicRedundancyChecker.h"

std::string PngHeader::toString() const
{
    std::stringstream sstr;
    sstr << "PngHeader" << "\n";
    sstr << "width: " << mWidth << "\n";
    sstr << "height: " << mHeight << "\n";
    sstr << "bitDepth: " << (int)mBitDepth << "\n";
    sstr << "cached CRC: " << mCachedCrc << "\n";

    sstr << mPngInfo.toString();
    return sstr.str();
}

uint32_t PngHeader::getLength() const
{
    return 13;
}

unsigned char PngHeader::getHighBitCheck() const
{
    return 0x89;
}

std::vector<unsigned char> PngHeader::getSignature() const
{
    return {13, 10, 26, 10};
}

std::string PngHeader::getFileName() const
{
    return "PNG";
}

const std::string& PngHeader::getChunkName() const
{
    return mName;
}

const std::vector<unsigned char>& PngHeader::getData() const
{
    return mData;
}

void PngHeader::updateData()
{
    mData.clear();
    unsigned num_bytes = sizeof(uint32_t);

    for(unsigned idx=0; idx<num_bytes;idx++)
    {
        mData.push_back(ByteUtils::getByteN(mWidth, idx));
    }

    for(unsigned idx=0; idx<num_bytes;idx++)
    {
        mData.push_back(ByteUtils::getByteN(mHeight, idx));
    }
    mData.push_back(mBitDepth);
    mData.push_back(static_cast<unsigned char>(mPngInfo.mColorType));
    mData.push_back(static_cast<unsigned char>(mPngInfo.mCompressionMethod));
    mData.push_back(static_cast<unsigned char>(mPngInfo.mFilterMethod));
    mData.push_back(static_cast<unsigned char>(mPngInfo.mInterlaceMethod));
}

uint32_t PngHeader::getCrc()
{
    CyclicRedundancyChecker crc_check;
    std::vector<unsigned char> char_data = StringUtils::toBytes(mName);
    for (auto c : char_data)
    {
        crc_check.addValue(c);
    }
    for (auto entry : mData)
    {
        crc_check.addValue(entry);
    }
    mCachedCrc = crc_check.getChecksum();
    return mCachedCrc;
}

void PngHeader::setPngInfo(const PngInfo& info)
{
    mPngInfo = info;
}

void PngHeader::setImageData(uint32_t width, uint32_t height, unsigned char bitDepth)
{
    mWidth = width;
    mHeight = height;
    mBitDepth = bitDepth;
}
