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

#include "include/core/SkCanvas.h"
#include "include/core/SkStream.h"
#include "include/docs/SkPDFDocument.h"
#include "include/private/SkMutex.h"
#include "include/private/SkTHash.h"
#include "src/pdf/SkPDFMetadata.h"
#include "src/pdf/SkPDFTag.h"

#include <atomic>
#include <vector>
#include <memory>

class SkExecutor;
class SkPDFDevice;
class SkPDFFont;
struct SkAdvancedTypefaceMetrics;
struct SkBitmapKey;
struct SkPDFFillGraphicState;
struct SkPDFImageShaderKey;
struct SkPDFStrokeGraphicState;

namespace SkPDFGradientShader {
struct Key;
struct KeyHash;
}  // namespace SkPDFGradientShader

const char* SkPDFGetNodeIdKey();

// Logically part of SkPDFDocument, but separate to keep similar functionality together.
class SkPDFOffsetMap {
public:
    void markStartOfDocument(const SkWStream*);
    void markStartOfObject(int referenceNumber, const SkWStream*);
    int objectCount() const;
    int emitCrossReferenceTable(SkWStream* s) const;
private:
    std::vector<int> fOffsets;
    size_t fBaseOffset = SIZE_MAX;
};


struct SkPDFNamedDestination {
    sk_sp<SkData> fName;
    SkPoint fPoint;
    SkPDFIndirectReference fPage;
};


struct SkPDFLink {
    enum class Type {
        kNone,
        kUrl,
        kNamedDestination,
    };

    SkPDFLink(Type type, SkData* data, const SkRect& rect, int nodeId)
        : fType(type)
        , fData(sk_ref_sp(data))
        , fRect(rect)
        , fNodeId(nodeId) {}
    const Type fType;
    // The url or named destination, depending on |fType|.
    const sk_sp<SkData> fData;
    const SkRect fRect;
    const int fNodeId;
};


/** Concrete implementation of SkDocument that creates PDF files. This
    class does not produced linearized or optimized PDFs; instead it
    it attempts to use a minimum amount of RAM. */
class SkPDFDocument : public SkDocument {
public:
    SkPDFDocument(SkWStream*, SkPDF::Metadata);
    ~SkPDFDocument() override;
    SkCanvas* onBeginPage(SkScalar, SkScalar) override;
    void onEndPage() override;
    void onClose(SkWStream*) override;
    void onAbort() override;

    /**
       Serialize the object, as well as any other objects it
       indirectly refers to.  If any any other objects have been added
       to the SkPDFObjNumMap without serializing them, they will be
       serialized as well.

       It might go without saying that objects should not be changed
       after calling serialize, since those changes will be too late.
     */
    SkPDFIndirectReference emit(const SkPDFObject&, SkPDFIndirectReference);
    SkPDFIndirectReference emit(const SkPDFObject& o) { return this->emit(o, this->reserveRef()); }

    template <typename T>
    void emitStream(const SkPDFDict& dict, T writeStream, SkPDFIndirectReference ref) {
        SkAutoMutexExclusive lock(fMutex);
        SkWStream* stream = this->beginObject(ref);
        dict.emitObject(stream);
        stream->writeText(" stream\n");
        writeStream(stream);
        stream->writeText("\nendstream");
        this->endObject();
    }

    const SkPDF::Metadata& metadata() const { return fMetadata; }

    SkPDFIndirectReference getPage(size_t pageIndex) const;
    SkPDFIndirectReference currentPage() const {
        return SkASSERT(!fPageRefs.empty()), fPageRefs.back();
    }
    // Used to allow marked content to refer to its corresponding structure
    // tree node, via a page entry in the parent tree. Returns -1 if no
    // mark ID.
    int createMarkIdForNodeId(int nodeId);
    // Used to allow annotations to refer to their corresponding structure
    // tree node, via the struct parent tree. Returns -1 if no struct parent
    // key.
    int createStructParentKeyForNodeId(int nodeId);

    std::unique_ptr<SkPDFArray> getAnnotations();

    SkPDFIndirectReference reserveRef() { return SkPDFIndirectReference{fNextObjectNumber++}; }

    // Returns a tag to prepend to a PostScript name of a subset font. Includes the '+'.
    SkString nextFontSubsetTag();

    SkExecutor* executor() const { return fExecutor; }
    void incrementJobCount();
    void signalJobComplete();
    size_t currentPageIndex() { return fPages.size(); }
    size_t pageCount() { return fPageRefs.size(); }

    const SkMatrix& currentPageTransform() const;

    // Canonicalized objects
    SkTHashMap<SkPDFImageShaderKey, SkPDFIndirectReference> fImageShaderMap;
    SkTHashMap<SkPDFGradientShader::Key, SkPDFIndirectReference, SkPDFGradientShader::KeyHash>
        fGradientPatternMap;
    SkTHashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
    SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
    SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
    SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
    SkTHashMap<uint32_t, SkPDFIndirectReference> fFontDescriptors;
    SkTHashMap<uint32_t, SkPDFIndirectReference> fType3FontDescriptors;
    SkTHashMap<uint64_t, SkPDFFont> fFontMap;
    SkTHashMap<SkPDFStrokeGraphicState, SkPDFIndirectReference> fStrokeGSMap;
    SkTHashMap<SkPDFFillGraphicState, SkPDFIndirectReference> fFillGSMap;
    SkPDFIndirectReference fInvertFunction;
    SkPDFIndirectReference fNoSmaskGraphicState;
    std::vector<std::unique_ptr<SkPDFLink>> fCurrentPageLinks;
    std::vector<SkPDFNamedDestination> fNamedDestinations;

private:
    SkPDFOffsetMap fOffsetMap;
    SkCanvas fCanvas;
    std::vector<std::unique_ptr<SkPDFDict>> fPages;
    std::vector<SkPDFIndirectReference> fPageRefs;

    sk_sp<SkPDFDevice> fPageDevice;
    std::atomic<int> fNextObjectNumber = {1};
    std::atomic<int> fJobCount = {0};
    uint32_t fNextFontSubsetTag = {0};
    SkUUID fUUID;
    SkPDFIndirectReference fInfoDict;
    SkPDFIndirectReference fXMP;
    SkPDF::Metadata fMetadata;
    SkScalar fRasterScale = 1;
    SkScalar fInverseRasterScale = 1;
    SkExecutor* fExecutor = nullptr;

    // For tagged PDFs.
    SkPDFTagTree fTagTree;

    SkMutex fMutex;
    SkSemaphore fSemaphore;

    void waitForJobs();
    SkWStream* beginObject(SkPDFIndirectReference);
    void endObject();
};

#endif  // SkPDFDocumentPriv_DEFINED
