/*
 * Copyright 2018 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/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/utils/SkRandom.h"
#include "tools/ToolUtils.h"

#include <array>
#include <vector>

namespace skiagm {

static constexpr int kPadSize = 20;
static constexpr int kBoxSize = 100;
static constexpr SkPoint kJitters[] = {{0, 0}, {.5f, .5f}, {2/3.f, 1/3.f}};

// Tests various corners of different angles falling on the same pixel, particularly to ensure
// analytic AA is working properly.
class SharedCornersGM : public GM {
public:
    SharedCornersGM() { this->setBGColor(ToolUtils::color_to_565(0xFF1A65D7)); }

protected:
    SkString onShortName() override {
        return SkString("sharedcorners");
    }

    SkISize onISize() override {
        constexpr int numRows = 3 * 2;
        constexpr int numCols = (1 + SK_ARRAY_COUNT(kJitters)) * 2;
        return SkISize::Make(numCols * (kBoxSize + kPadSize) + kPadSize,
                             numRows * (kBoxSize + kPadSize) + kPadSize);
    }

    void onOnceBeforeDraw() override {
        fFillPaint.setColor(SK_ColorWHITE);
        fFillPaint.setAntiAlias(true);

        fWireFramePaint = fFillPaint;
        fWireFramePaint.setStyle(SkPaint::kStroke_Style);

    }

    void onDraw(SkCanvas* canvas) override {
        canvas->translate(kPadSize, kPadSize);
        canvas->save();

        // Adjacent rects.
        this->drawTriangleBoxes(canvas,
                {{0,  0}, {40,  0}, {80,  0}, {120,  0},
                 {0, 20}, {40, 20}, {80, 20}, {120, 20},
                          {40, 40}, {80, 40},
                          {40, 60}, {80, 60}},
                {{{0, 1, 4}}, {{1, 5, 4}},
                 {{5, 1, 6}}, {{1, 2, 6}},
                 {{2, 3, 6}}, {{3, 7, 6}},
                 {{8, 5, 9}}, {{5, 6, 9}},
                 {{10, 8, 11}}, {{8, 9, 11}}});

        // Obtuse angles.
        this->drawTriangleBoxes(canvas,
                {{ 0, 0}, {10, 0}, {20, 0},
                 { 0, 2},          {20, 2},
                          {10, 4},
                 { 0, 6},          {20, 6},
                 { 0, 8}, {10, 8}, {20, 8}},
                {{{3, 1, 4}}, {{4, 5, 3}}, {{6, 5, 7}}, {{7, 9, 6}},
                 {{0, 1, 3}}, {{1, 2, 4}},
                 {{3, 5, 6}}, {{5, 4, 7}},
                 {{6, 9, 8}}, {{9, 7, 10}}});

        canvas->restore();
        canvas->translate((kBoxSize + kPadSize) * 4, 0);

        // Right angles.
        this->drawTriangleBoxes(canvas,
                {{0, 0}, {-1, 0}, {0, -1}, {1, 0}, {0, 1}},
                {{{0, 1, 2}}, {{0, 2, 3}}, {{0, 3, 4}}, {{0, 4, 1}}});

        // Acute angles.
        SkRandom rand;
        std::vector<SkPoint> pts;
        std::vector<std::array<int, 3>> indices;
        SkScalar theta = 0;
        pts.push_back({0, 0});
        while (theta < 2*SK_ScalarPI) {
            pts.push_back({SkScalarCos(theta), SkScalarSin(theta)});
            if (pts.size() > 2) {
                indices.push_back({{0, (int)pts.size() - 2, (int)pts.size() - 1}});
            }
            theta += rand.nextRangeF(0, SK_ScalarPI/3);
        }
        indices.push_back({{0, (int)pts.size() - 1, 1}});
        this->drawTriangleBoxes(canvas, pts, indices);
    }

    void drawTriangleBoxes(SkCanvas* canvas, const std::vector<SkPoint>& points,
                           const std::vector<std::array<int, 3>>& triangles) {
        SkPath path;
        path.setFillType(SkPathFillType::kEvenOdd);
        path.setIsVolatile(true);
        for (const std::array<int, 3>& triangle : triangles) {
            path.moveTo(points[triangle[0]]);
            path.lineTo(points[triangle[1]]);
            path.lineTo(points[triangle[2]]);
            path.close();
        }
        SkScalar scale = kBoxSize / std::max(path.getBounds().height(), path.getBounds().width());
        path.transform(SkMatrix::Scale(scale, scale));

        this->drawRow(canvas, path);
        canvas->translate(0, kBoxSize + kPadSize);

        SkMatrix rot;
        rot.setRotate(45, path.getBounds().centerX(), path.getBounds().centerY());
        path.transform(rot);
        this->drawRow(canvas, path);
        canvas->translate(0, kBoxSize + kPadSize);

        rot.setRotate(-45 - 69.38111f, path.getBounds().centerX(), path.getBounds().centerY());
        path.transform(rot);
        this->drawRow(canvas, path);
        canvas->translate(0, kBoxSize + kPadSize);
    }

    void drawRow(SkCanvas* canvas, const SkPath& path) {
        SkAutoCanvasRestore acr(canvas, true);
        const SkRect& bounds = path.getBounds();
        canvas->translate((kBoxSize - bounds.width()) / 2 - bounds.left(),
                          (kBoxSize - bounds.height()) / 2 - bounds.top());

        canvas->drawPath(path, fWireFramePaint);
        canvas->translate(kBoxSize + kPadSize, 0);

        for (SkPoint jitter : kJitters) {
            {
                SkAutoCanvasRestore acr(canvas, true);
                canvas->translate(jitter.x(), jitter.y());
                canvas->drawPath(path, fFillPaint);
            }
            canvas->translate(kBoxSize + kPadSize, 0);
        }
    }

    SkPaint fWireFramePaint;
    SkPaint fFillPaint;
};

DEF_GM(return new SharedCornersGM;)

}  // namespace skiagm
