/*
 * 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 "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
