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

#include <VectorDrawable.h>
#include <gtest/gtest.h>

#include <SkClipStack.h>
#include <SkSurface_Base.h>
#include <string.h>
#include "AnimationContext.h"
#include "DamageAccumulator.h"
#include "FatalTestCanvas.h"
#include "IContextFactory.h"
#include "SkiaCanvas.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaRecordingCanvas.h"
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"

using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::skiapipeline;

namespace {

static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
                         std::function<void(const SkCanvas&)> opValidateCallback) {
    static const int CANVAS_WIDTH = 100;
    static const int CANVAS_HEIGHT = 100;
    class PropertyTestCanvas : public TestCanvasBase {
    public:
        PropertyTestCanvas(std::function<void(const SkCanvas&)> callback)
                : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT), mCallback(callback) {}
        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
            EXPECT_EQ(mDrawCounter++, 0);
            mCallback(*this);
        }
        void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) {
            SkCanvas::onClipRRect(rrect, op, style);
        }
        std::function<void(const SkCanvas&)> mCallback;
    };

    auto node = TestUtils::createSkiaNode(
            0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
            [propSetupCallback](RenderProperties& props, SkiaRecordingCanvas& canvas) {
                propSetupCallback(props);
                SkPaint paint;
                paint.setColor(SK_ColorWHITE);
                canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
            });

    PropertyTestCanvas canvas(opValidateCallback);
    RenderNodeDrawable drawable(node.get(), &canvas, true);
    canvas.drawDrawable(&drawable);
    EXPECT_EQ(1, canvas.mDrawCounter);
}
}

TEST(RenderNodeDrawable, renderPropClipping) {
    testProperty(
            [](RenderProperties& properties) {
                properties.setClipToBounds(true);
                properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400));
            },
            [](const SkCanvas& canvas) {
                EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas))
                        << "Clip rect should be intersection of node bounds and clip bounds";
            });
}

TEST(RenderNodeDrawable, renderPropRevealClip) {
    testProperty(
            [](RenderProperties& properties) {
                properties.mutableRevealClip().set(true, 50, 50, 25);
            },
            [](const SkCanvas& canvas) {
                EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), TestUtils::getClipBounds(&canvas));
            });
}

TEST(RenderNodeDrawable, renderPropOutlineClip) {
    testProperty(
            [](RenderProperties& properties) {
                properties.mutableOutline().setShouldClip(true);
                properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
            },
            [](const SkCanvas& canvas) {
                EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(&canvas));
            });
}

TEST(RenderNodeDrawable, renderPropTransform) {
    testProperty(
            [](RenderProperties& properties) {
                properties.setLeftTopRightBottom(10, 10, 110, 110);

                SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
                properties.setStaticMatrix(&staticMatrix);

                // ignored, since static overrides animation
                SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
                properties.setAnimationMatrix(&animationMatrix);

                properties.setTranslationX(10);
                properties.setTranslationY(20);
                properties.setScaleX(0.5f);
                properties.setScaleY(0.7f);
            },
            [](const SkCanvas& canvas) {
                Matrix4 matrix;
                matrix.loadTranslate(10, 10, 0);  // left, top
                matrix.scale(1.2f, 1.2f, 1);      // static matrix
                // ignore animation matrix, since static overrides it

                // translation xy
                matrix.translate(10, 20);

                // scale xy (from default pivot - center)
                matrix.translate(50, 50);
                matrix.scale(0.5f, 0.7f, 1);
                matrix.translate(-50, -50);
                Matrix4 actual(canvas.getTotalMatrix());
                EXPECT_MATRIX_APPROX_EQ(matrix, actual) << "Op draw matrix must match expected "
                                                           "combination of transformation "
                                                           "properties";
            });
}
