/*
 * Copyright 2010 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkPDFTypes_DEFINED
#define SkPDFTypes_DEFINED

#include "SkRefCnt.h"
#include "SkScalar.h"
#include "SkString.h"
#include "SkTDArray.h"
#include "SkTHash.h"
#include "SkTypes.h"

class SkPDFObjNumMap;
class SkPDFObject;
class SkPDFSubstituteMap;
class SkWStream;

/** \class SkPDFObject

    A PDF Object is the base class for primitive elements in a PDF file.  A
    common subtype is used to ease the use of indirect object references,
    which are common in the PDF format.

*/
class SkPDFObject : public SkRefCnt {
public:
    SK_DECLARE_INST_COUNT(SkPDFObject);

    /** Subclasses must implement this method to print the object to the
     *  PDF file.
     *  @param catalog  The object catalog to use.
     *  @param stream   The writable output stream to send the output to.
     */
    // TODO(halcanary): make this method const
    virtual void emitObject(SkWStream* stream,
                            const SkPDFObjNumMap& objNumMap,
                            const SkPDFSubstituteMap& substitutes) = 0;

    /**
     *  Adds all transitive dependencies of this object to the
     *  catalog.  Implementations should respect the catalog's object
     *  substitution map.
     */
    virtual void addResources(SkPDFObjNumMap* catalog,
                              const SkPDFSubstituteMap& substitutes) const {}

private:
    typedef SkRefCnt INHERITED;
};

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

/**
   A SkPDFUnion is a non-virtualized implementation of the
   non-compound, non-specialized PDF Object types: Name, String,
   Number, Boolean.
 */
class SkPDFUnion {
public:
    // u.move() is analogous to std::move(u). It returns an rvalue.
    SkPDFUnion move() { return static_cast<SkPDFUnion&&>(*this); }
    // Move contstructor and assignemnt operator destroy the argument
    // and steal their references (if needed).
    SkPDFUnion(SkPDFUnion&& other);
    SkPDFUnion& operator=(SkPDFUnion&& other);

    ~SkPDFUnion();

    /** The following nine functions are the standard way of creating
        SkPDFUnion objects. */

    static SkPDFUnion Int(int32_t);

    static SkPDFUnion Bool(bool);

    static SkPDFUnion Scalar(SkScalar);

    /** These two functions do NOT take ownership of ptr, and do NOT
        copy the string.  Suitable for passing in static const
        strings. For example:
          SkPDFUnion n = SkPDFUnion::Name("Length");
          SkPDFUnion u = SkPDFUnion::String("Identity"); */

    /** SkPDFUnion::Name(const char*) assumes that the passed string
        is already a valid name (that is: it has no control or
        whitespace characters).  This will not copy the name. */
    static SkPDFUnion Name(const char*);

    /** SkPDFUnion::String will encode the passed string.  This will
        not copy the name. */
    static SkPDFUnion String(const char*);

    /** SkPDFUnion::Name(const SkString&) does not assume that the
        passed string is already a valid name and it will escape the
        string. */
    static SkPDFUnion Name(const SkString&);

    /** SkPDFUnion::String will encode the passed string. */
    static SkPDFUnion String(const SkString&);

    /** This function DOES take ownership of the object. E.g.
          SkAutoTUnref<SkPDFDict> dict(new SkPDFDict);
          dict->insert(.....);
          SkPDFUnion u = SkPDFUnion::Object(dict.detach()) */
    static SkPDFUnion Object(SkPDFObject*);

    /** This function DOES take ownership of the object. E.g.
          SkAutoTUnref<SkPDFBitmap> image(
                 SkPDFBitmap::Create(fCanon, bitmap));
          SkPDFUnion u = SkPDFUnion::ObjRef(image.detach()) */
    static SkPDFUnion ObjRef(SkPDFObject*);

    /** These two non-virtual methods mirror SkPDFObject's
        corresponding virtuals. */
    void emitObject(SkWStream*,
                    const SkPDFObjNumMap&,
                    const SkPDFSubstituteMap&) const;
    void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const;

    bool isName() const;

private:
    union {
        int32_t fIntValue;
        bool fBoolValue;
        SkScalar fScalarValue;
        const char* fStaticString;
        char fSkString[sizeof(SkString)];
        SkPDFObject* fObject;
    };
    enum class Type : char {
        /** It is an error to call emitObject() or addResources() on an
            kDestroyed object. */
        kDestroyed = 0,
        kInt,
        kBool,
        kScalar,
        kName,
        kString,
        kNameSkS,
        kStringSkS,
        kObjRef,
        kObject,
    };
    Type fType;

    SkPDFUnion(Type);
    // We do not now need copy constructor and copy assignment, so we
    // will disable this functionality.
    SkPDFUnion& operator=(const SkPDFUnion&) = delete;
    SkPDFUnion(const SkPDFUnion&) = delete;
};
SK_COMPILE_ASSERT(sizeof(SkString) == sizeof(void*), SkString_size);

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

/**  This class is a SkPDFUnion with SkPDFObject virtuals attached. */
// TODO(halcanary): 99% of the uses of this class should be
// transitioned to using a bare SkPDFUnion inside an array or dict.
class SkPDFAtom : public SkPDFObject {
public:
    void emitObject(SkWStream* stream,
                    const SkPDFObjNumMap& objNumMap,
                    const SkPDFSubstituteMap& substitutes) final;
    void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final;

protected:
    SkPDFAtom(SkPDFUnion&& v) : fValue(v.move()) {}

private:
    const SkPDFUnion fValue;
    typedef SkPDFObject INHERITED;
};

/** The following six classes exist only to ease transition to SkPDFUnion. */
class SkPDFObjRef : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFObjRef);
    explicit SkPDFObjRef(SkPDFObject* obj)
        : INHERITED(SkPDFUnion::ObjRef(SkRef(obj))) {}
    typedef SkPDFAtom INHERITED;
};

class SkPDFInt : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFInt);
    explicit SkPDFInt(int32_t value) : INHERITED(SkPDFUnion::Int(value)) {}
    typedef SkPDFAtom INHERITED;
};

class SkPDFBool : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFBool);
    explicit SkPDFBool(bool value) : INHERITED(SkPDFUnion::Bool(value)) {}
    typedef SkPDFAtom INHERITED;
};

class SkPDFScalar : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFScalar);
    explicit SkPDFScalar(SkScalar value)
        : INHERITED(SkPDFUnion::Scalar(value)) {}
    static void Append(SkScalar value, SkWStream* stream);
    typedef SkPDFAtom INHERITED;
};

class SkPDFString : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFString);
    explicit SkPDFString(const char value[])
        : INHERITED(SkPDFUnion::String(value)) {}
    explicit SkPDFString(const SkString& value)
        : INHERITED(SkPDFUnion::String(value)) {}

    static SkString FormatString(const char* input, size_t len);

    static const size_t kMaxLen = 65535;

private:
    typedef SkPDFAtom INHERITED;
};

class SkPDFName : public SkPDFAtom {
public:
    SK_DECLARE_INST_COUNT(SkPDFName);
    /** Create a PDF name object. Maximum length is 127 bytes. */
    explicit SkPDFName(const char name[])
        : INHERITED(SkPDFUnion::Name(SkString(name))) {}
    explicit SkPDFName(const SkString& name)
        : INHERITED(SkPDFUnion::Name(name)) {}

    static const size_t kMaxLen = 127;

private:
    typedef SkPDFAtom INHERITED;
};

/** \class SkPDFArray

    An array object in a PDF.
*/
class SkPDFArray : public SkPDFObject {
public:
    SK_DECLARE_INST_COUNT(SkPDFArray)

    static const int kMaxLen = 8191;

    /** Create a PDF array. Maximum length is 8191.
     */
    SkPDFArray();
    virtual ~SkPDFArray();

    // The SkPDFObject interface.
    virtual void emitObject(SkWStream* stream,
                            const SkPDFObjNumMap& objNumMap,
                            const SkPDFSubstituteMap& substitutes) override;
    virtual void addResources(SkPDFObjNumMap*,
                              const SkPDFSubstituteMap&) const override;

    /** The size of the array.
     */
    int size() const;

    /** Preallocate space for the given number of entries.
     *  @param length The number of array slots to preallocate.
     */
    void reserve(int length);

    /** Append the object to the end of the array and increments its ref count.
     *  @param value The value to add to the array.
     *  @return The value argument is returned.
     */
    // DEPRECATED
    SkPDFObject* append(SkPDFObject* value);

    /** Appends a value to the end of the array.
     *  @param value The value to add to the array.
     */
    void appendInt(int32_t);
    void appendBool(bool);
    void appendScalar(SkScalar);
    void appendName(const char[]);
    void appendName(const SkString&);
    void appendString(const char[]);
    void appendString(const SkString&);
    /** appendObject and appendObjRef take ownership of the passed object */
    void appendObject(SkPDFObject*);
    void appendObjRef(SkPDFObject*);

private:
    SkTDArray<SkPDFUnion> fValues;
    void append(SkPDFUnion&& value);
    typedef SkPDFObject INHERITED;
};

/** \class SkPDFDict

    A dictionary object in a PDF.
*/
class SkPDFDict : public SkPDFObject {
public:
    SK_DECLARE_INST_COUNT(SkPDFDict)

    /** Create a PDF dictionary. Maximum number of entries is 4095.
     */
    SkPDFDict();

    /** Create a PDF dictionary with a Type entry.
     *  @param type   The value of the Type entry.
     */
    explicit SkPDFDict(const char type[]);

    virtual ~SkPDFDict();

    // The SkPDFObject interface.
    virtual void emitObject(SkWStream* stream,
                            const SkPDFObjNumMap& objNumMap,
                            const SkPDFSubstituteMap& substitutes) override;
    virtual void addResources(SkPDFObjNumMap*,
                              const SkPDFSubstituteMap&) const override;

    /** The size of the dictionary.
     */
    int size() const;

    /** Add the value to the dictionary with the given key.  Refs value.
     *  @param key   The key for this dictionary entry.
     *  @param value The value for this dictionary entry.
     *  @return The value argument is returned.
     */
    // DEPRECATED
    SkPDFObject* insert(SkPDFName* key, SkPDFObject* value);
    // DEPRECATED
    SkPDFObject* insert(const char key[], SkPDFObject* value);

    /** Add the value to the dictionary with the given key.  Takes
     *  ownership of the object.
     *  @param key   The text of the key for this dictionary entry.
     *  @param value The value for this dictionary entry.
     */
    void insertObject(const char key[], SkPDFObject* value);
    void insertObject(const SkString& key, SkPDFObject* value);
    void insertObjRef(const char key[], SkPDFObject* value);
    void insertObjRef(const SkString& key, SkPDFObject* value);

    /** Add the value to the dictionary with the given key.
     *  @param key   The text of the key for this dictionary entry.
     *  @param value The value for this dictionary entry.
     */
    void insertInt(const char key[], int32_t value);
    void insertInt(const char key[], size_t value);
    void insertScalar(const char key[], SkScalar value);
    void insertName(const char key[], const char nameValue[]);
    void insertName(const char key[], const SkString& nameValue);
    void insertString(const char key[], const char value[]);
    void insertString(const char key[], const SkString& value);

    /** Remove all entries from the dictionary.
     */
    void clear();

private:
    struct Record {
        SkPDFUnion fKey;
        SkPDFUnion fValue;
    };
    SkTDArray<Record> fRecords;
    static const int kMaxLen = 4095;

    void set(const SkPDFUnion& name, const SkPDFUnion& value);
    void set(SkPDFUnion&& name, SkPDFUnion&& value);

    typedef SkPDFObject INHERITED;
};

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

/** \class SkPDFObjNumMap

    The PDF Object Number Map manages object numbers.  It is used to
    create the PDF cross reference table.
*/
class SkPDFObjNumMap : SkNoncopyable {
public:
    /** Add the passed object to the catalog.
     *  @param obj         The object to add.
     *  @return True iff the object was not already added to the catalog.
     */
    bool addObject(SkPDFObject* obj);

    /** Get the object number for the passed object.
     *  @param obj         The object of interest.
     */
    int32_t getObjectNumber(SkPDFObject* obj) const;

    const SkTDArray<SkPDFObject*>& objects() const { return fObjects; }

private:
    SkTDArray<SkPDFObject*> fObjects;
    SkTHashMap<SkPDFObject*, int32_t> fObjectNumbers;
};

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

/** \class SkPDFSubstituteMap

    The PDF Substitute Map manages substitute objects and owns the
    substitutes.
*/
class SkPDFSubstituteMap : SkNoncopyable {
public:
    ~SkPDFSubstituteMap();
    /** Set substitute object for the passed object.
        Refs substitute.
     */
    void setSubstitute(SkPDFObject* original, SkPDFObject* substitute);

    /** Find and return any substitute object set for the passed object. If
     *  there is none, return the passed object.
     */
    SkPDFObject* getSubstitute(SkPDFObject* object) const;

    SkPDFObject* operator()(SkPDFObject* o) const {
        return this->getSubstitute(o);
    }

private:
    SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap;
};

#endif
