/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradient.h"
#include "src/utils/SkPatchUtils.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"

static sk_sp<SkShader> make_shader() {
    const SkColor4f colors[] = {
        SkColors::kRed, SkColors::kCyan, SkColors::kGreen, SkColors::kWhite, SkColors::kMagenta,
        SkColors::kBlue, SkColors::kYellow,
    };
    const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } };

    return SkShaders::LinearGradient(pts, {{colors, {}, SkTileMode::kMirror}, {}});
}

static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
    //draw control points
    SkPaint paint;
    SkPoint bottom[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetBottomCubic(cubics, bottom);
    SkPoint top[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetTopCubic(cubics, top);
    SkPoint left[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetLeftCubic(cubics, left);
    SkPoint right[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetRightCubic(cubics, right);

    paint.setColor(SK_ColorBLACK);
    paint.setStrokeWidth(0.5f);
    SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
    canvas->drawPoints(SkCanvas::kLines_PointMode, {bottom, 4}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {bottom + 1, 2}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {top, 4}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {left, 4}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {right, 4}, paint);

    canvas->drawPoints(SkCanvas::kLines_PointMode, {top + 1, 2}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {left + 1, 2}, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, {right + 1, 2}, paint);

    paint.setStrokeWidth(2);

    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, {corners, 4}, paint);

    paint.setColor(SK_ColorBLUE);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, {bottom + 1, 2}, paint);

    paint.setColor(SK_ColorCYAN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, {top + 1, 2}, paint);

    paint.setColor(SK_ColorYELLOW);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, {left + 1, 2}, paint);

    paint.setColor(SK_ColorGREEN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, {right + 1, 2}, paint);
}

// The order of the colors and points is clockwise starting at upper-left corner.
const SkPoint gCubics[SkPatchUtils::kNumCtrlPts] = {
    //top points
    {100,100},{150,50},{250,150}, {300,100},
    //right points
    {250, 150},{350,250},
    //bottom points
    {300,300},{250,250},{150,350},{100,300},
    //left points
    {50,250},{150,150}
};

const SkPoint gTexCoords[SkPatchUtils::kNumCorners] = {
    {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f}
};


static void dopatch(SkCanvas* canvas, const SkColor colors[], sk_sp<SkImage> img,
                    const SkMatrix* localMatrix) {
    SkPaint paint;
    paint.setColor(SK_ColorGREEN);

    const SkBlendMode modes[] = {
        SkBlendMode::kSrc,
        SkBlendMode::kDst,
        SkBlendMode::kColorDodge,
    };

    SkPoint texStorage[4];
    const SkPoint* tex = gTexCoords;

    sk_sp<SkShader> shader;
    if (img) {
        SkScalar w = img->width();
        SkScalar h = img->height();
        shader = img->makeShader(SkSamplingOptions(), localMatrix);
        texStorage[0].set(0, 0);
        texStorage[1].set(w, 0);
        texStorage[2].set(w, h);
        texStorage[3].set(0, h);
        tex = texStorage;
    } else {
        shader = make_shader();
    }

    canvas->save();
    for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 4; x++) {
            canvas->save();
            canvas->translate(x * 350.0f, y * 350.0f);
            switch (x) {
                case 0:
                    canvas->drawPatch(gCubics, nullptr, nullptr, modes[y], paint);
                    break;
                case 1:
                    canvas->drawPatch(gCubics, colors, nullptr, modes[y], paint);
                    break;
                case 2:
                    paint.setShader(shader);
                    canvas->drawPatch(gCubics, nullptr, tex, modes[y], paint);
                    paint.setShader(nullptr);
                    break;
                case 3:
                    paint.setShader(shader);
                    canvas->drawPatch(gCubics, colors, tex, modes[y], paint);
                    paint.setShader(nullptr);
                    break;
                default:
                    break;
            }

            draw_control_points(canvas, gCubics);
            canvas->restore();
        }
    }
    canvas->restore();
}

DEF_SIMPLE_GM(patch_primitive, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
    };
    dopatch(canvas, colors, nullptr, nullptr);
}
DEF_SIMPLE_GM(patch_image, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
    };
    dopatch(canvas, colors, ToolUtils::GetResourceAsImage("images/mandrill_128.png"), nullptr);
}
DEF_SIMPLE_GM(patch_image_persp, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
    };
    SkMatrix localM;
    localM.reset();
    localM[6] = 0.00001f;    // force perspective
    dopatch(canvas, colors, ToolUtils::GetResourceAsImage("images/mandrill_128.png"), &localM);
}
DEF_SIMPLE_GM(patch_alpha, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, 0x0000FF00, SK_ColorBLUE, 0x00FF00FF,
    };
    dopatch(canvas, colors, nullptr, nullptr);
}

// These two should look the same (one patch, one simple path)
DEF_SIMPLE_GM(patch_alpha_test, canvas, 550, 250) {
    canvas->translate(-75, -75);

    const SkColor colors[SkPatchUtils::kNumCorners] = {
        0x80FF0000, 0x80FF0000, 0x80FF0000, 0x80FF0000,
    };
    SkPaint paint;
    canvas->drawPatch(gCubics, colors, nullptr, SkBlendMode::kDst, paint);

    canvas->translate(300, 0);

    SkPath path = SkPathBuilder()
                  .moveTo(gCubics[0])
                  .cubicTo(gCubics[ 1], gCubics[ 2], gCubics[ 3])
                  .cubicTo(gCubics[ 4], gCubics[ 5], gCubics[ 6])
                  .cubicTo(gCubics[ 7], gCubics[ 8], gCubics[ 9])
                  .cubicTo(gCubics[10], gCubics[11], gCubics[ 0])
                  .detach();
    paint.setColor(colors[0]);
    canvas->drawPath(path, paint);
}

