/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPdfContext.h"
#include "SkPdfNativeDoc.h"
#include "SkPdfReporter.h"
#include "SkPdfTokenLooper.h"

///////////////////////////////////////////////////////////////////////////////

class PdfMainLooper : public SkPdfTokenLooper {
public:
    PdfMainLooper(SkPdfNativeTokenizer* tokenizer,
                  SkPdfContext* pdfContext,
                  SkCanvas* canvas)
        : INHERITED(tokenizer, pdfContext, canvas) {}

    virtual SkPdfResult consumeToken(PdfToken& token) SK_OVERRIDE;
    virtual void loop() SK_OVERRIDE;

private:
    typedef SkPdfTokenLooper INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

SkPdfContext::SkPdfContext(SkPdfNativeDoc* doc)
    : fPdfDoc(doc)
{
    SkASSERT(fPdfDoc != NULL);
}

void SkPdfContext::parseStream(SkPdfNativeObject* stream, SkCanvas* canvas) {
    if (NULL == stream) {
        // Nothing to parse.
        return;
    }

    SkPdfNativeTokenizer tokenizer(stream, &fTmpPageAllocator, fPdfDoc);
    PdfMainLooper looper(&tokenizer, this, canvas);
    looper.loop();
}

///////////////////////////////////////////////////////////////////////////////

// FIXME (scroggo): This probably belongs in a debugging file.
// For reportRenderStats declaration.
#include "SkPdfRenderer.h"

// Temp code to measure what operands fail.
template <typename T> class SkTDictWithDefaultConstructor : public SkTDict<T> {
public:
    SkTDictWithDefaultConstructor() : SkTDict<T>(10) {}
};

SkTDictWithDefaultConstructor<int> gRenderStats[kCount_SkPdfResult];

const char* gRenderStatsNames[kCount_SkPdfResult] = {
    "Success",
    "Partially implemented",
    "Not yet implemented",
    "Ignore Error",
    "Error",
    "Unsupported/Unknown"
};

// Declared in SkPdfRenderer.h. Should be moved to a central debugging location.
void reportPdfRenderStats() {
    for (int i = 0 ; i < kCount_SkPdfResult; i++) {
        SkTDict<int>::Iter iter(gRenderStats[i]);
        const char* key;
        int value = 0;
        while ((key = iter.next(&value)) != NULL) {
            SkDebugf("%s: %s -> count %i\n", gRenderStatsNames[i], key, value);
        }
    }
}

#include "SkPdfOps.h"

SkPdfResult PdfMainLooper::consumeToken(PdfToken& token) {
    if (token.fType == kKeyword_TokenType && token.fKeywordLength < 256)
    {
        PdfOperatorRenderer pdfOperatorRenderer = NULL;
        if (gPdfOps.find(token.fKeyword, token.fKeywordLength, &pdfOperatorRenderer) &&
                    pdfOperatorRenderer) {
            // Main work is done by pdfOperatorRenderer(...)
            SkPdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, this);

            int cnt = 0;
            gRenderStats[result].find(token.fKeyword, token.fKeywordLength, &cnt);
            gRenderStats[result].set(token.fKeyword, token.fKeywordLength, cnt + 1);
        } else {
            int cnt = 0;
            gRenderStats[kUnsupported_SkPdfResult].find(token.fKeyword,
                                                        token.fKeywordLength,
                                                        &cnt);
            gRenderStats[kUnsupported_SkPdfResult].set(token.fKeyword,
                                                       token.fKeywordLength,
                                                       cnt + 1);
        }
    }
    else if (token.fType == kObject_TokenType)
    {
        fPdfContext->fObjectStack.push( token.fObject );
    }
    else {
        // TODO(edisonn): store the keyword as a object, so we can track the location in file,
        //                and report where the error was triggered
        SkPdfReport(kCodeWarning_SkPdfIssueSeverity, kNYI_SkPdfIssue, token.fKeyword, NULL,
                    fPdfContext);
        return kIgnoreError_SkPdfResult;
    }
    return kOK_SkPdfResult;
}

void PdfMainLooper::loop() {
    PdfToken token;
    while (fTokenizer->readToken(&token, true)) {
        this->consumeToken(token);
    }
}
