#include "FontReader.h"
#include "TrueTypeFont.h"

#include "File.h"
#include "BinaryStream.h"

#include <iostream>
#include <sstream>

FontReader::~FontReader()
{

}

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

bool FontReader::readOffsetSubtable()
{
    mOffsetSubtable.scaler_type = *BinaryStream::getNextDWord(mFile->GetInHandle());
    mCurrentOffset += 4;

    mOffsetSubtable.num_tables = *BinaryStream::getNextWord(mFile->GetInHandle());
    mCurrentOffset += 2;

    mOffsetSubtable.search_range = *BinaryStream::getNextWord(mFile->GetInHandle());
    mCurrentOffset += 2;

    mOffsetSubtable.entry_selector = *BinaryStream::getNextWord(mFile->GetInHandle());
    mCurrentOffset += 2;

    mOffsetSubtable.range_shift = *BinaryStream::getNextWord(mFile->GetInHandle());
    mCurrentOffset += 2;

    return true;
}

void FontReader::logOffsetSubtable()
{
    std::stringstream sstr;
    sstr << "Offset Subtable\n";
    sstr << "scaler_type: " << mOffsetSubtable.scaler_type << "\n";

    sstr << "num_tables: " << mOffsetSubtable.num_tables << "\n";

    sstr << "search_range: " << mOffsetSubtable.search_range << "\n";

    sstr << "entry_selector: " << mOffsetSubtable.entry_selector << "\n";

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

void FontReader::readTableDirectory()
{
    mTables.clear();
    for (unsigned idx=0; idx<mOffsetSubtable.num_tables; idx++)
    {
        Table table;
        BinaryStream::getNextString(mFile->GetInHandle(), table.name, 4);
        mCurrentOffset += 4;

        table.checksum = *BinaryStream::getNextDWord(mFile->GetInHandle());
        mCurrentOffset += 4;

        table.offset = *BinaryStream::getNextDWord(mFile->GetInHandle());
        mCurrentOffset += 4;

        table.length = *BinaryStream::getNextDWord(mFile->GetInHandle());
        mCurrentOffset += 4;

        logTable(table);
        mTables.push_back(table);
    }
}

void FontReader::logTable(const Table& table)
{
    std::stringstream sstr;
    sstr << "Table\n";
    sstr << "name: " << table.name << "\n";

    sstr << "checksum: " << table.checksum << "\n";

    sstr << "offset: " << table.offset << "\n";

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

void FontReader::readTable()
{
    std::string working_table_name;
    for (const auto& table : mTables)
    {
        if (mCurrentOffset == table.offset)
        {
            working_table_name = table.name;
            break;
        }
    }

    if (working_table_name == "head")
    {
        readHeadTable();
    }

}

void FontReader::readHeadTable()
{
    std::cout << "Reading head table" << std::endl;

    TrueTypeFont::HeadTable table;

    table.version = *BinaryStream::getNextDWord(mFile->GetInHandle());
    table.fontRevision = *BinaryStream::getNextDWord(mFile->GetInHandle());
    table.checksumAdjustment = *BinaryStream::getNextDWord(mFile->GetInHandle());
    table.magicNumber = *BinaryStream::getNextDWord(mFile->GetInHandle());
    mCurrentOffset += 16;

    table.flags = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.unitsPerEm = *BinaryStream::getNextWord(mFile->GetInHandle());
    mCurrentOffset += 4;

    table.created = *BinaryStream::getNextQWord(mFile->GetInHandle());
    table.modified = *BinaryStream::getNextQWord(mFile->GetInHandle());
    mCurrentOffset += 16;

    table.xMin = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.yMin = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.xMax = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.yMax = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.macStyle = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.lowestRecPPEM = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.fontDirectionHint = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.indexToLocFormat = *BinaryStream::getNextWord(mFile->GetInHandle());
    table.glyphDataFormat = *BinaryStream::getNextWord(mFile->GetInHandle());

    mCurrentOffset += 18;

    auto working_ttf_font = dynamic_cast<TrueTypeFont*>(mWorkingFont.get());
    working_ttf_font->setHeadTable(table);
    std::cout << working_ttf_font->logHeadTable() << std::endl;
}


std::unique_ptr<IFont> FontReader::read()
{
    mWorkingFont = std::make_unique<TrueTypeFont>();

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

    readOffsetSubtable();
    std::cout << "Current offset: " << mCurrentOffset << std::endl;

    logOffsetSubtable();

    readTableDirectory();
    std::cout << "Current offset: " << mCurrentOffset << std::endl;

    for (unsigned idx=0; idx<mOffsetSubtable.num_tables; idx++)
    {
        readTable();
        std::cout << "Current offset: " << mCurrentOffset << std::endl;
        break;
    }

    mFile->Close();




    return std::move(mWorkingFont);
}

