/*
 * 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;
}

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++}; }

    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};
    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
