#include "PdfPage.h"

#include "PdfObject.h"
#include "PdfStream.h"
#include "PdfXRefTable.h"
#include "PdfPageTree.h"

std::string PdfProcSet::toString(PdfXRefTable* xRefTable)
{
    updateDictionary();
    auto content = getStringPrefix();
    content += mDictionary.toString();
    content += "[/PDF]\n";
    content += getStringSuffix();
    xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
    return content;
}

std::string PdfFont::toString(PdfXRefTable* xRefTable)
{
    updateDictionary();
    auto content = getStringPrefix();
    content += mDictionary.toString();
    content += getStringSuffix();
    xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
    return content;
}

void PdfFont::updateDictionary()
{
    mDictionary.addStringItem("Type", "/Font");
    mDictionary.addStringItem("Subtype", "/Type1");
    mDictionary.addStringItem("Name", "/F1");
    mDictionary.addStringItem("BaseFont", "/Helvetica");
    mDictionary.addStringItem("Encoding", "/MacRomanEncoding");
}

PdfPage::PdfPage(PdfPageTree* parent)
    : mParent(parent)
{
    mContent = std::make_unique<PdfStream>();

    std::string pageContent = "BT\n";
    pageContent += "/F1 24 Tf\n";
    pageContent += "100 700 Td\n";
    pageContent += "(Hello \nWorld) Tj\n";
    pageContent += "ET";

    mContent->setContent(pageContent);
    mProcSet = std::make_unique<PdfProcSet>();

    mDefaultFont = std::make_unique<PdfFont>();
}

unsigned PdfPage::indexObjects(unsigned count)
{
    auto newCount = count + 1;
    mObjectNumber = newCount;
    newCount = mContent->indexObjects(newCount);
    newCount = mProcSet->indexObjects(newCount);
    newCount = mDefaultFont->indexObjects(newCount);
    return newCount;
}

std::string PdfPage::toString(PdfXRefTable* xRefTable)
{
    updateDictionary();
    auto content = getStringPrefix();
    content += mDictionary.toString();
    content += getStringSuffix();
    xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);

    content += mContent->toString(xRefTable);
    content += mProcSet->toString(xRefTable);
    content += mDefaultFont->toString(xRefTable);
    return content;
}

void PdfPage::updateDictionary()
{
    std::string mediaBox = "[0 0 " + std::to_string(mWidth) + " " + std::to_string(mHeight) + "]";
    mDictionary.addStringItem("Type", "/Page");
    mDictionary.addStringItem("MediaBox", mediaBox);
    mDictionary.addStringItem("Parent", mParent->getRefString());
    mDictionary.addStringItem("Contents", mContent->getRefString());

    auto resourcesDict = std::make_unique<PdfDictionary>();
    resourcesDict->addStringItem("ProcSet", mProcSet->getRefString());

    auto fontDict = std::make_unique<PdfDictionary>();
    fontDict->addStringItem("F1", mDefaultFont->getRefString());
    resourcesDict->addDictItem("Font", std::move(fontDict));

    mDictionary.addDictItem("Resources", std::move(resourcesDict));
}
