/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

// TODO: Can we get the dependencies scoped down more?
#include "CanvasOps.h"
#include "CanvasOpBuffer.h"
#include <SaveFlags.h>

#include <SkRasterClip.h>
#include <ui/FatVector.h>

#include <optional>

namespace android::uirenderer {

// Exists to avoid forcing all this common logic into the templated class
class CanvasStateHelper {
protected:
    CanvasStateHelper(int width, int height);
    ~CanvasStateHelper() = default;

    struct SaveEntry {
        bool clip : 1 = false;
        bool matrix : 1 = false;
        bool layer : 1 = false;
    };

    constexpr SaveEntry saveEntryForLayer() {
        return {
            .clip = true,
            .matrix = true,
            .layer = true,
        };
    }

    constexpr SaveEntry flagsToSaveEntry(SaveFlags::Flags flags) {
        return SaveEntry {
            .clip = static_cast<bool>(flags & SaveFlags::Clip),
            .matrix = static_cast<bool>(flags & SaveFlags::Matrix),
            .layer = false
        };
    }

    bool internalSave(SaveEntry saveEntry);

    void internalSaveLayer(const SkCanvas::SaveLayerRec& layerRec) {
        internalSave({
            .clip = true,
            .matrix = true,
            .layer = true
        });
        internalClipRect(*layerRec.fBounds, SkClipOp::kIntersect);
    }

    bool internalRestore();

    void internalClipRect(const SkRect& rect, SkClipOp op);
    void internalClipPath(const SkPath& path, SkClipOp op);

    SkIRect mInitialBounds;
    FatVector<SaveEntry, 6> mSaveStack;
    FatVector<SkMatrix, 6> mTransformStack;
    FatVector<SkConservativeClip, 6> mClipStack;

    size_t mCurrentTransformIndex;
    size_t mCurrentClipIndex;

    const SkConservativeClip& clip() const {
        return mClipStack[mCurrentClipIndex];
    }

    SkConservativeClip& clip() {
        return mClipStack[mCurrentClipIndex];
    }

    void resetState(int width, int height);

public:
    int saveCount() const { return mSaveStack.size(); }

    SkRect getClipBounds() const;
    bool quickRejectRect(float left, float top, float right, float bottom) const;
    bool quickRejectPath(const SkPath& path) const;

    const SkMatrix& transform() const {
        return mTransformStack[mCurrentTransformIndex];
    }

    SkMatrix& transform() {
        return mTransformStack[mCurrentTransformIndex];
    }

    // For compat with existing HWUI Canvas interface
    void getMatrix(SkMatrix* outMatrix) const {
        *outMatrix = transform();
    }

    void setMatrix(const SkMatrix& matrix) {
        transform() = matrix;
    }

    void concat(const SkMatrix& matrix) {
        transform().preConcat(matrix);
    }

    void rotate(float degrees) {
        SkMatrix m;
        m.setRotate(degrees);
        concat(m);
    }

    void scale(float sx, float sy) {
        SkMatrix m;
        m.setScale(sx, sy);
        concat(m);
    }

    void skew(float sx, float sy) {
        SkMatrix m;
        m.setSkew(sx, sy);
        concat(m);
    }

    void translate(float dx, float dy) {
        transform().preTranslate(dx, dy);
    }
};

// Front-end canvas that handles queries, up-front state, and produces CanvasOp<> output downstream
template <typename CanvasOpReceiver>
class CanvasFrontend final : public CanvasStateHelper {
public:
    template<class... Args>
    CanvasFrontend(int width, int height, Args&&... args) : CanvasStateHelper(width, height),
            mReceiver(std::forward<Args>(args)...) { }
    ~CanvasFrontend() = default;

    void save(SaveFlags::Flags flags = SaveFlags::MatrixClip) {
        if (internalSave(flagsToSaveEntry(flags))) {
            submit<CanvasOpType::Save>({});
        }
    }

    void restore() {
        if (internalRestore()) {
            submit<CanvasOpType::Restore>({});
        }
    }

    template <CanvasOpType T>
    void draw(CanvasOp<T>&& op) {
        // The front-end requires going through certain front-doors, which these aren't.
        static_assert(T != CanvasOpType::Save, "Must use CanvasFrontend::save() call instead");
        static_assert(T != CanvasOpType::Restore, "Must use CanvasFrontend::restore() call instead");

        if constexpr (T == CanvasOpType::SaveLayer) {
            internalSaveLayer(op.saveLayerRec);
        }
        if constexpr (T == CanvasOpType::SaveBehind) {
            // Don't use internalSaveLayer as this doesn't apply clipping, it's a "regular" save
            // But we do want to flag it as a layer, such that restore is Definitely Required
            internalSave(saveEntryForLayer());
        }
        if constexpr (T == CanvasOpType::ClipRect) {
            internalClipRect(op.rect, op.op);
        }
        if constexpr (T == CanvasOpType::ClipPath) {
            internalClipPath(op.path, op.op);
        }

        submit(std::move(op));
    }

    const CanvasOpReceiver& receiver() const { return *mReceiver; }

    CanvasOpReceiver finish() {
        auto ret = std::move(mReceiver.value());
        mReceiver.reset();
        return std::move(ret);
    }

    template<class... Args>
    void reset(int newWidth, int newHeight, Args&&... args) {
        resetState(newWidth, newHeight);
        mReceiver.emplace(std::forward<Args>(args)...);
    }

private:
    std::optional<CanvasOpReceiver> mReceiver;

    template <CanvasOpType T>
    void submit(CanvasOp<T>&& op) {
        mReceiver->push_container(CanvasOpContainer(std::move(op), transform()));
    }
};

} // namespace android::uirenderer
