#include "PdfDocument.h"

#include "PdfObject.h"
#include "PdfDocumentCatalog.h"
#include "PdfPageTree.h"
#include "PdfPage.h"
#include "PdfOutline.h"
#include "PdfXRefTable.h"

PdfDocument::PdfDocument()
{
    mXRefTable = std::make_unique<PdfXRefTable>();
    mCatalog = std::make_unique<PdfDocumentCatalog>();
}

PdfDocument::~PdfDocument()
{

}

std::string PdfDocument::ToString()
{
    IndexObjects();
    auto content = GetHeaderString();
    content += GetBodyString();

    content += GetXRefString();

    content += GetTrailerString();

    content += "%%EOF\n";
    return content;
}

std::string PdfDocument::GetHeaderString()
{
    auto content = "%PDF-" + mVersion + "\n";
    mXRefOffset = content.size();
    mXRefTable->AddRecord(content.size(), 65535, true);
    return content;
}

std::string PdfDocument::GetBodyString()
{
    const auto content = mCatalog->ToString(mXRefTable.get());
    mXRefOffset += content.size();
    return content;
}

std::string PdfDocument::GetXRefString()
{
    return mXRefTable->ToString();
}

std::string PdfDocument::GetTrailerString()
{
    const auto numObjects = mXRefTable->GetNumEntries();
    mTrailer.AddStringItem("Size", std::to_string(numObjects));
    mTrailer.AddStringItem("Root", mCatalog->GetRefString());

    std::string content = "trailer\n";
    content += mTrailer.ToString();

    content += "startxref\n";
    content += std::to_string(mXRefOffset) + "\n";
    return content;
}

void PdfDocument::IndexObjects()
{
    mCatalog->IndexObjects(0);
}

