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

// TODO(edisonn): this file not commented much on purpose.
// It will probably need heavy refactoring soon anyway to support all encodings, fonts and
// proper text sizing and spacing

#ifndef SkPdfFont_DEFINED
#define SkPdfFont_DEFINED

#include "SkPdfContext.h"
#include "SkPdfHeaders_autogen.h"
#include "SkPdfMapper_autogen.h"
#include "SkPdfUtils.h"
#include "SkTypeface.h"
#include "SkTDict.h"
#include "SkUtils.h"

class SkPdfType0Font;
class SkPdfType1Font;
class SkPdfType3Font;
class SkPdfTrueTypeFont;
class SkPdfMultiMasterFont;
class SkPdfFont;

struct SkPdfStandardFontEntry {
    // We don't own this pointer!
    const char* fName;
    bool fIsBold;
    bool fIsItalic;
    SkPdfStandardFontEntry()
    : fName(NULL),
      fIsBold(false),
      fIsItalic(false) {}

    SkPdfStandardFontEntry(const char* name, bool bold, bool italic)
        : fName(name),
          fIsBold(bold),
          fIsItalic(italic) {}
};

SkTDict<SkPdfStandardFontEntry>& getStandardFonts();
SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName);

struct SkUnencodedText {
    void* text;
    int len;

public:
    SkUnencodedText(const SkPdfString* obj) {
        text = (void*)obj->c_str();
        len = (int) obj->lenstr();
    }
};

struct SkDecodedText {
    uint16_t* text;
    int len;
public:
    unsigned int operator[](int i) const { return text[i]; }
    int size() const { return len; }
};

struct SkUnicodeText {
    uint16_t* text;
    int len;

public:
    unsigned int operator[](int i) const { return text[i]; }
    int size() const { return len; }
};

class SkPdfEncoding {
public:
    virtual ~SkPdfEncoding() {}
    virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
    static SkPdfEncoding* fromName(const char* name);
};

SkTDict<SkPdfEncoding*>& getStandardEncodings();

class SkPdfToUnicode {
    SkPdfNativeDoc* fParsed;
    // TODO(edisonn): hide public members
public:
    unsigned short* fCMapEncoding;
    unsigned char* fCMapEncodingFlag;

    SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
};


class SkPdfIdentityHEncoding : public SkPdfEncoding {
public:
    virtual ~SkPdfIdentityHEncoding() {}
    virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
        // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?

        uint16_t* text = (uint16_t*)textIn.text;
        textOut->text = new uint16_t[textIn.len / 2];
        textOut->len = textIn.len / 2;

        for (int i = 0; i < textOut->len; i++) {
            textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
        }

        return true;
    }

    static SkPdfIdentityHEncoding* instance() {
        static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
        return inst;
    }
};

// TODO(edisonn): using this one when no encoding is specified
class SkPdfDefaultEncoding : public SkPdfEncoding {
public:
    virtual ~SkPdfDefaultEncoding() {}
    virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
        // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?

        unsigned char* text = (unsigned char*)textIn.text;
        textOut->text = new uint16_t[textIn.len];
        textOut->len = textIn.len;

        for (int i = 0; i < textOut->len; i++) {
            textOut->text[i] = text[i];
        }

        return true;
    }

    static SkPdfDefaultEncoding* instance() {
        static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
        return inst;
    }
};

class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
public:
    virtual ~SkPdfCIDToGIDMapIdentityEncoding() {}
    virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
        // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?

        uint16_t* text = (uint16_t*)textIn.text;
        textOut->text = new uint16_t[textIn.len / 2];
        textOut->len = textIn.len / 2;

        for (int i = 0; i < textOut->len; i++) {
            textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
        }

        return true;
    }

    static SkPdfCIDToGIDMapIdentityEncoding* instance() {
        static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
        return inst;
    }
};

class SkPdfFont {
public:
    SkPdfFont* fBaseFont;
    SkPdfEncoding* fEncoding;
    SkPdfToUnicode* fToUnicode;


public:
    SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}

    virtual ~SkPdfFont() {
        // TODO(edisonn): NYI (will leak for now)
    }

    const SkPdfEncoding* encoding() const {return fEncoding;}

    void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext,
                  SkCanvas* canvas) {
        for (int i = 0 ; i < text.size(); i++) {
            canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
#ifdef PDF_TRACE
            SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0));
            pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1);
            printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()),
                                             SkScalarToDouble(point.y()));
#endif  // PDF_TRACE

#ifdef PDF_TRACE_DRAWTEXT
            SkPaint col;
            col.setColor(SK_ColorMAGENTA);
            SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0),
                                           SkDoubleToScalar(0.0),
                                           SkDoubleToScalar(10.0),
                                           SkDoubleToScalar(10.0));
            canvas->save();
            canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
            canvas->drawRect(rect, col);
            canvas->restore();
#endif
            double width = drawOneChar(text[i], paint, pdfContext, canvas);
            pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width),
                                                              SkDoubleToScalar(0.0));
        }
    }

    void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
        if (fToUnicode) {
            textOut->text = new uint16_t[textIn.len];
            textOut->len = textIn.len;
            for (int i = 0; i < textIn.len; i++) {
                textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
            }
        } else {
            textOut->text = textIn.text;
            textOut->len = textIn.len;
        }
    };

    inline unsigned int ToUnicode(unsigned int ch) const {
        if (fToUnicode && fToUnicode->fCMapEncoding) {
            return fToUnicode->fCMapEncoding[ch];
        } else {
            return ch;
        }
    };

    static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
    static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}

    static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc,
                                                       SkPdfType0FontDictionary* dict);
    static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc,
                                                       SkPdfType1FontDictionary* dict);
    static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc,
                                                       SkPdfType3FontDictionary* dict);
    static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
                                                             SkPdfTrueTypeFontDictionary* dict);
    static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(
            SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);

    static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc,
                                             SkPdfFontDescriptorDictionary* fd,
                                             bool loadFromName = true);

public:
    virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
                               SkCanvas* canvas) = 0;
    virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;

private:
    static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
};

class SkPdfStandardFont : public SkPdfFont {
    SkTypeface* fTypeface;

public:
    SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}

public:
    virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
                               SkCanvas* canvas) {
        paint->setTypeface(fTypeface);
        paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);

        unsigned long ch4 = ch;
        char utf8[10];
        size_t len = SkUTF8_FromUnichar((SkUnichar) ch4, utf8);

        canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);

        SkScalar textWidth = paint->measureText(utf8, len);
        return SkScalarToDouble(textWidth);
    }

    virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
};

class SkPdfType0Font : public SkPdfFont {
public:
    SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);

public:

    virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
                               SkCanvas* canvas) {
        return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
    }

    virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
    }
};

class SkPdfType1Font : public SkPdfFont {
public:
    SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
        if (dict->has_FontDescriptor()) {
            fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
        } else {
            fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
        }

        if (dict->isEncodingAName(doc)) {
            fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
        } else if (dict->isEncodingADictionary(doc)) {
            //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
        }
        dict->FontDescriptor(doc);
    }

public:
      virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
                                 SkCanvas* canvas) {
          return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
      }

      virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {

      }
};

class SkPdfTrueTypeFont : public SkPdfType1Font {
public:
    SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
            : SkPdfType1Font(doc, dict) {}
};

class SkPdfMultiMasterFont : public SkPdfType1Font {
public:
    SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict)
            : SkPdfType1Font(doc, dict) {}
};
/*
class CIDToGIDMap {
    virtual unsigned int map(unsigned int cid) = 0;
    static CIDToGIDMap* fromName(const char* name);
};

class CIDToGIDMap_Identity {
    virtual unsigned int map(unsigned int cid) { return cid; }

    static CIDToGIDMap_Identity* instance() {
        static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
        return inst;
    }
};

CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
    // The only one supported right now is Identity
    if (strcmp(name, "Identity") == 0) {
        return CIDToGIDMap_Identity::instance();
    }

#ifdef PDF_TRACE
    // TODO(edisonn): warning/report
    printf("Unknown CIDToGIDMap: %s\n", name);
#endif
    return NULL;
}
CIDToGIDMap* fCidToGid;
*/

class SkPdfType3Font : public SkPdfFont {
    struct Type3FontChar {
        SkPdfNativeObject* fObj;
        double fWidth;
    };

    SkPdfDictionary* fCharProcs;
    SkPdfEncodingDictionary* fEncodingDict;
    unsigned int fFirstChar;
    unsigned int fLastChar;

    SkRect fFontBBox;
    SkMatrix fFonMatrix;

    Type3FontChar* fChars;

public:
    SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
        fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());

        if (dict->has_Encoding()) {
            if (dict->isEncodingAName(parsed)) {
                 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
            } else if (dict->isEncodingAEncodingdictionary(parsed)) {
                 // No encoding.
                 fEncoding = SkPdfDefaultEncoding::instance();
                 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
            }
        }

        // null?
        fCharProcs = dict->CharProcs(parsed);

        fToUnicode = NULL;
        if (dict->has_ToUnicode()) {
            fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
        }

        fFirstChar = (unsigned int)dict->FirstChar(parsed);
        fLastChar = (unsigned int)dict->LastChar(parsed);
        fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();

        if (dict->has_FontBBox()) {
            fFontBBox = dict->FontBBox(parsed);
        }

        fChars = new Type3FontChar[fLastChar - fFirstChar + 1];

        memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));

        const SkPdfArray* widths = dict->Widths(parsed);
        for (unsigned int i = 0 ; i < widths->size(); i++) {
            if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
                fChars[i].fWidth = (*widths)[i]->numberValue();
            } else {
                // TODO(edisonn): report pdf corruption
            }
        }

        const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
        unsigned int j = fFirstChar;
        for (unsigned int i = 0 ; i < diffs->size(); i++) {
            if ((*diffs)[i]->isInteger()) {
                j = (unsigned int)(*diffs)[i]->intValue();
            } else if ((*diffs)[i]->isName()) {
                if (j >= fFirstChar && j <= fLastChar) {
                    fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
                } else {
                    // TODO(edisonn): report pdf corruption
                }
                j++;
            } else {
                // TODO(edisonn): report bad pdf
            }
        }
    }

public:
    virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
                               SkCanvas* canvas) {
        if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
            return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
        }

#ifdef PDF_TRACE
        printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
        if (ToUnicode(ch) == 'A') {
            printf("break;\n");
        }
#endif

        // TODO(edisonn): is it better to resolve the reference at load time, or now?
        doType3Char(pdfContext,
                    canvas,
                    pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj),
                    fFontBBox,
                    fFonMatrix,
                    pdfContext->fGraphicsState.fCurFontSize);

        // TODO(edisonn): verify/test translate code, not tested yet
        pdfContext->fGraphicsState.fMatrixTm.preTranslate(
                SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize *
                                     fChars[ch - fFirstChar].fWidth),
                SkDoubleToScalar(0.0));
        return fChars[ch - fFirstChar].fWidth;
    }

    virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
};

#endif  // SkPdfFont_DEFINED
