/*
 * 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 "tools/ganesh/TestCanvas.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;

namespace skiatest {

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

void TestCanvas<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());
        }
    }
}

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

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

TestCanvas<SkRemoteSlugTestKey>::TestCanvas(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.
TestCanvas<SkRemoteSlugTestKey>::~TestCanvas() {
    static_cast<ClientHandleManager*>(fClientHandleManager.get())->unlock();
}

void TestCanvas<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());
                }
            }
        }
    }
}

}  // namespace skiatest
