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

#include "src/utils/SkTestCanvas.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"  // IWYU pragma: keep
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkDebug.h"
#include "include/private/chromium/SkChromeRemoteGlyphCache.h"
#include "include/private/chromium/Slug.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkDevice.h"
#include "src/text/GlyphRun.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <vector>

class SkPaint;

SkTestCanvas<SkSlugTestKey>::SkTestCanvas(SkCanvas* canvas)
        : SkCanvas(sk_ref_sp(canvas->rootDevice())) {}

void SkTestCanvas<SkSlugTestKey>::onDrawGlyphRunList(
        const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) {
    SkRect bounds = glyphRunList.sourceBoundsWithOrigin();
    if (this->internalQuickReject(bounds, paint)) {
        return;
    }
    auto layer = this->aboutToDraw(paint, &bounds);
    if (layer) {
        if (glyphRunList.hasRSXForm()) {
            this->SkCanvas::onDrawGlyphRunList(glyphRunList, layer->paint());
        } else {
            auto slug = this->onConvertGlyphRunListToSlug(glyphRunList, layer->paint());
            this->drawSlug(slug.get(), layer->paint());
        }
    }
}

SkTestCanvas<SkSerializeSlugTestKey>::SkTestCanvas(SkCanvas* canvas)
        : SkCanvas(sk_ref_sp(canvas->rootDevice())) {}

void SkTestCanvas<SkSerializeSlugTestKey>::onDrawGlyphRunList(
        const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) {
    SkRect bounds = glyphRunList.sourceBoundsWithOrigin();
    if (this->internalQuickReject(bounds, paint)) {
        return;
    }
    auto layer = this->aboutToDraw(paint, &bounds);
    if (layer) {
        if (glyphRunList.hasRSXForm()) {
            this->SkCanvas::onDrawGlyphRunList(glyphRunList, layer->paint());
        } else {
            sk_sp<SkData> bytes;
            {
                auto slug = this->onConvertGlyphRunListToSlug(glyphRunList, layer->paint());
                if (slug != nullptr) {
                    bytes = slug->serialize();
                }
            }
            {
                if (bytes != nullptr) {
                    auto slug = sktext::gpu::Slug::Deserialize(bytes->data(), bytes->size());
                    this->drawSlug(slug.get(), layer->paint());
                }
            }
        }
    }
}


// A do nothing handle manager for the remote strike server.
class ServerHandleManager : public SkStrikeServer::DiscardableHandleManager {
public:
    SkDiscardableHandleId createHandle() override {
        return 0;
    }

    bool lockHandle(SkDiscardableHandleId id) override {
        return true;
    }

    bool isHandleDeleted(SkDiscardableHandleId id) override {
        return false;
    }
};

// Lock the strikes into the cache for the length of the test. This handler is tied to the lifetime
// of the canvas used to render the entire test.
class ClientHandleManager : public SkStrikeClient::DiscardableHandleManager {
public:
    bool deleteHandle(SkDiscardableHandleId id) override {
        return fIsLocked;
    }

    void assertHandleValid(SkDiscardableHandleId id) override {
        DiscardableHandleManager::assertHandleValid(id);
    }

    void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override {

    }

    void notifyReadFailure(const ReadFailureData& data) override {
        DiscardableHandleManager::notifyReadFailure(data);
    }

    void unlock() {
        fIsLocked = true;
    }

private:
    bool fIsLocked{false};
};

SkTestCanvas<SkRemoteSlugTestKey>::SkTestCanvas(SkCanvas* canvas)
        : SkCanvas(sk_ref_sp(canvas->rootDevice()))
        , fServerHandleManager(new ServerHandleManager{})
        , fClientHandleManager(new ClientHandleManager{})
        , fStrikeServer(fServerHandleManager.get())
        , fStrikeClient(fClientHandleManager) {}

// Allow the strikes to be freed from the strike cache after the test has been drawn.
SkTestCanvas<SkRemoteSlugTestKey>::~SkTestCanvas() {
    static_cast<ClientHandleManager*>(fClientHandleManager.get())->unlock();
}

void SkTestCanvas<SkRemoteSlugTestKey>::onDrawGlyphRunList(
        const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) {
    SkRect bounds = glyphRunList.sourceBoundsWithOrigin();
    if (this->internalQuickReject(bounds, paint)) {
        return;
    }
    auto layer = this->aboutToDraw(paint, &bounds);
    if (layer) {
        if (glyphRunList.hasRSXForm()) {
            this->SkCanvas::onDrawGlyphRunList(glyphRunList, layer->paint());
        } else {
            sk_sp<SkData> slugBytes;
            std::vector<uint8_t> glyphBytes;
            {
                auto analysisCanvas = fStrikeServer.makeAnalysisCanvas(
                        this->topDevice()->width(),
                        this->topDevice()->height(),
                        this->fProps,
                        this->topDevice()->imageInfo().refColorSpace(),
                        // TODO: Where should we get this value from?
                        /*DFTSupport=*/ true);

                // TODO: Move the analysis canvas processing up to the via to handle a whole
                //  document at a time. This is not the correct way to handle the CTM; it doesn't
                //  work for layers.
                analysisCanvas->setMatrix(this->getLocalToDevice());
                auto slug = analysisCanvas->onConvertGlyphRunListToSlug(glyphRunList,
                                                                        layer->paint());
                if (slug != nullptr) {
                    slugBytes = slug->serialize();
                }
                fStrikeServer.writeStrikeData(&glyphBytes);
            }
            {
                if (!glyphBytes.empty()) {
                    fStrikeClient.readStrikeData(glyphBytes.data(), glyphBytes.size());
                }
                if (slugBytes != nullptr) {
                    auto slug = sktext::gpu::Slug::Deserialize(
                            slugBytes->data(), slugBytes->size(), &fStrikeClient);
                    this->drawSlug(slug.get(), layer->paint());
                }
            }
        }
    }
}
