/*
 * Copyright (C) 2017 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

#include "RenderNode.h"
#include "SkiaDisplayList.h"

namespace android {
namespace uirenderer {
namespace skiapipeline {

/**
 * DumpOpsCanvas prints drawing ops from a SkiaDisplayList into a std::ostream. Children render
 * nodes are walked recursively and their drawing ops are printed as well.
 */
class DumpOpsCanvas : public SkCanvas {
public:
    DumpOpsCanvas(std::ostream& output, int level, SkiaDisplayList& displayList)
            : mOutput(output)
            , mLevel(level)
            , mDisplayList(displayList)
            , mIdent((level + 1) * 2, ' ') {}

protected:
    void onClipRect(const SkRect& rect, SkClipOp, ClipEdgeStyle) override {
        mOutput << mIdent << "clipRect" << std::endl;
    }

    void onClipRRect(const SkRRect& rrect, SkClipOp, ClipEdgeStyle) override {
        mOutput << mIdent << "clipRRect" << std::endl;
    }

    void onClipPath(const SkPath& path, SkClipOp, ClipEdgeStyle) override {
        mOutput << mIdent << "clipPath" << std::endl;
    }

    void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {
        mOutput << mIdent << "clipRegion" << std::endl;
    }

    void onDrawPaint(const SkPaint&) override { mOutput << mIdent << "drawPaint" << std::endl; }

    void onDrawPath(const SkPath&, const SkPaint&) override {
        mOutput << mIdent << "drawPath" << std::endl;
    }

    void onDrawRect(const SkRect&, const SkPaint&) override {
        mOutput << mIdent << "drawRect" << std::endl;
    }

    void onDrawRegion(const SkRegion&, const SkPaint&) override {
        mOutput << mIdent << "drawRegion" << std::endl;
    }

    void onDrawOval(const SkRect&, const SkPaint&) override {
        mOutput << mIdent << "drawOval" << std::endl;
    }

    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override {
        mOutput << mIdent << "drawArc" << std::endl;
    }

    void onDrawRRect(const SkRRect&, const SkPaint&) override {
        mOutput << mIdent << "drawRRect" << std::endl;
    }

    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override {
        mOutput << mIdent << "drawDRRect" << std::endl;
    }

    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {
        mOutput << mIdent << "drawText" << std::endl;
    }

    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override {
        mOutput << mIdent << "drawPosText" << std::endl;
    }

    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override {
        mOutput << mIdent << "drawPosTextH" << std::endl;
    }

    void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,
                          const SkPaint&) override {
        mOutput << mIdent << "drawTextOnPath" << std::endl;
    }

    void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
                           const SkPaint&) override {
        mOutput << mIdent << "drawTextRSXform" << std::endl;
    }

    void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override {
        mOutput << mIdent << "drawTextBlob" << std::endl;
    }

    void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
        mOutput << mIdent << "drawImage" << std::endl;
    }

    void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
                         const SkPaint*) override {
        mOutput << mIdent << "drawImageNine" << std::endl;
    }

    void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
                         SrcRectConstraint) override {
        mOutput << mIdent << "drawImageRect" << std::endl;
    }

    void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
                            const SkPaint*) override {
        mOutput << mIdent << "drawImageLattice" << std::endl;
    }

    void onDrawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {
        mOutput << mIdent << "drawPoints" << std::endl;
    }

    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override {
        mOutput << mIdent << "drawPicture" << std::endl;
    }

    void onDrawDrawable(SkDrawable* drawable, const SkMatrix*) override {
        mOutput << mIdent;
        auto renderNodeDrawable = getRenderNodeDrawable(drawable);
        if (nullptr != renderNodeDrawable) {
            mOutput << std::string(mLevel * 2, ' ') << "drawRenderNode";
            renderNodeDrawable->getRenderNode()->output(mOutput, mLevel + 1);
            return;
        }
        auto glFunctorDrawable = getGLFunctorDrawable(drawable);
        if (nullptr != glFunctorDrawable) {
            mOutput << std::string(mLevel * 2, ' ') << "drawGLFunctorDrawable" << std::endl;
            return;
        }

        mOutput << std::string(mLevel * 2, ' ') << "drawDrawable" << std::endl;
    }

private:
    RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
        for (auto& child : mDisplayList.mChildNodes) {
            if (drawable == &child) {
                return &child;
            }
        }
        return nullptr;
    }

    GLFunctorDrawable* getGLFunctorDrawable(SkDrawable* drawable) {
        for (auto& child : mDisplayList.mChildFunctors) {
            if (drawable == &child) {
                return &child;
            }
        }
        return nullptr;
    }

    std::ostream& mOutput;
    int mLevel;
    SkiaDisplayList& mDisplayList;
    std::string mIdent;
};

};  // namespace skiapipeline
};  // namespace uirenderer
};  // namespace android
