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

#include "samplecode/Sample.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkM44.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkVertices.h"
#include "include/private/SkTPin.h"

#include <unordered_set>

static SkPaint paint(SkColor color,
                     float strokeWidth = -1.f,
                     SkPaint::Join join = SkPaint::kMiter_Join) {
    SkPaint paint;
    paint.setColor(color);
    paint.setAntiAlias(true);
    if (strokeWidth >= 0.f) {
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(strokeWidth);
        paint.setStrokeJoin(join);
    }
    return paint;
}

// Singular values for [a b][c d] 2x2 matrix, unordered.
static std::pair<float, float> singular_values(float a, float b, float c, float d) {
    float s1 = a*a + b*b + c*c + d*d;

    float e = a*a + b*b - c*c - d*d;
    float f = a*c + b*d;
    float s2 = SkScalarSqrt(e*e + 4*f*f);

    float singular1 = SkScalarSqrt(0.5f * (s1 + s2));
    float singular2 = SkScalarSqrt(0.5f * (s1 - s2));

    return {singular1, singular2};
}

static constexpr float kAARadius = 10.f;

//              [m00 m01 * m03]                                 [f(u,v)]
// Assuming M = [m10 m11 * m13], define the projected p'(u,v) = [g(u,v)] where
//              [ *   *  *  * ]
//              [m30 m31 * m33]
//                                                        [x]     [u]
// f(u,v) = x(u,v) / w(u,v), g(u,v) = y(u,v) / w(u,v) and [y] = M*[v]
//                                                        [*] =   [0]
//                                                        [w]     [1]
//
// x(u,v) = m00*u + m01*v + m03
// y(u,v) = m10*u + m11*v + m13
// w(u,v) = m30*u + m31*v + m33
//
// dx/du = m00, dx/dv = m01,
// dy/du = m10, dy/dv = m11
// dw/du = m30, dw/dv = m31
//
// df/du = (dx/du*w - x*dw/du)/w^2 = (m00*w - m30*x)/w^2
// df/dv = (dx/dv*w - x*dw/dv)/w^2 = (m01*w - m31*x)/w^2
// dg/du = (dy/du*w - y*dw/du)/w^2 = (m10*w - m30*y)/w^2
// dg/dv = (dy/dv*w - y*dw/du)/w^2 = (m11*w - m31*y)/w^2
//
// Singular values of [df/du df/dv] define perspective correct minimum and maximum scale factors
//                    [dg/du dg/dv]
// for M evaluated at  (u,v)
static float local_aa_radius(const SkM44& matrix, const SkV2& p) {
    SkV4 devP = matrix.map(p.x, p.y, 0.f, 1.f);

    const float dxdu = matrix.rc(0,0);
    const float dxdv = matrix.rc(0,1);
    const float dydu = matrix.rc(1,0);
    const float dydv = matrix.rc(1,1);
    const float dwdu = matrix.rc(3,0);
    const float dwdv = matrix.rc(3,1);

    float invW2 = 1.f / (devP.w * devP.w);
    // non-persp has invW2 = 1, devP.w = 1, dwdu = 0, dwdv = 0
    float dfdu = (devP.w*dxdu - devP.x*dwdu) * invW2; // non-persp -> dxdu -> m00
    float dfdv = (devP.w*dxdv - devP.x*dwdv) * invW2; // non-persp -> dxdv -> m01
    float dgdu = (devP.w*dydu - devP.y*dwdu) * invW2; // non-persp -> dydu -> m10
    float dgdv = (devP.w*dydv - devP.y*dwdv) * invW2; // non-persp -> dydv -> m11

    // no-persp, this is the singular values of [m00,m01][m10,m11], which is just the upper 2x2
    // and equivalent to SkMatrix::getMinmaxScales().
    auto [sv1, sv2] = singular_values(dfdu, dfdv, dgdu, dgdv);

    // The minimum and maximum singular values of the above matrix represent the min and maximum
    // scale factors that could be applied by the 'matrix'. So if 'p' is moved 1px locally it will
    // move between [min, max]px after transformation. Thus, moving 1/min px locally will move
    // between [1, max/min]px after transformation, ensuring the device-space offset exceeds the
    // minimum AA offset for analytic AA.
    float minScale = std::min(sv1, sv2);
    return kAARadius / minScale;
}

static constexpr float kMiterScale = 1.f;
static constexpr float kBevelScale = 0.0f;
static constexpr float kRoundScale = SK_FloatSqrt2 - 1.f;

struct LocalCornerVert {
    SkV2 fPosition;     // In unit square that each corner is normalized to
    SkV2 fNormal;       // Direction that AA outset is applied in

    float fStrokeScale; // Signed scale factor applied to external stroke radius, should be [-1,1]
    float fMirrorScale; // Scale fPosition.yx, along with external join-scale, should be [0,1].
    float fCenterWeight; // Added to external center scale, > 0 forces point to center instead.

    // 'cornerMapping' is a row-major 2x2 matrix [[x y], [z w]] to flip and rotate the normalized
    // positions into the local coord space.
    SkV3 transform(const SkM44& m, const SkV4& cornerMapping, const SkV2& cornerPt,
                   const SkV2& cornerRadii, const SkV4& devCenter, float centerWeight,
                   float strokeRadius, float joinScale, float localAARadius) const {
        const bool snapToCenter = centerWeight + fCenterWeight > 0.f;
        if (snapToCenter) {
            return {devCenter.x, devCenter.y, devCenter.w};
        } else {
            // Normalized position before any additional AA offsets
            SkV2 normalizedPos = fPosition + joinScale*fMirrorScale*SkV2{fPosition.y, fPosition.x};
            // scales the normalized unit corner to the actual radii of the corner, before any AA
            // offsets are added.
            SkV2 scale = cornerRadii + SkV2{fStrokeScale*strokeRadius, fStrokeScale*strokeRadius};
            normalizedPos = scale*normalizedPos - cornerRadii;

            if (fStrokeScale < 0.f) {
                // An inset, which means it might cross over or might be forced to the center
                SkV2 maxInset = scale - SkV2{localAARadius, localAARadius};
                if (maxInset.x < 0.f || maxInset.y < 0.f) {
                    normalizedPos =
                            SkV2{std::min(maxInset.x, 0.f), std::min(maxInset.y, 0.f)}
                            - cornerRadii;
                } else {
                    normalizedPos += localAARadius * fNormal;
                }
            } // else no normal offsetting, or device-space offsetting

            SkV2 localPos =
                   {cornerMapping.x*normalizedPos.x + cornerMapping.y*normalizedPos.y + cornerPt.x,
                    cornerMapping.z*normalizedPos.x + cornerMapping.w*normalizedPos.y + cornerPt.y};
            SkV4 devPos = m.map(localPos.x, localPos.y, 0.f, 1.f);

            const bool deviceSpaceNormal =
                    fStrokeScale > 0.f && (fNormal.x > 0.f || fNormal.y > 0.f);
            if (deviceSpaceNormal) {
                SkV2 devNorm;
                {
                    // To calculate a device-space normal, we use the normal matrix (A^-1)^T where
                    // A is CTM * T(cornerPt) * cornerMapping * scale. We inline the calculation
                    // of (T(cornerPt)*cornerMapping*scale)^-1^T * [nx, ny, 0, 0] = N', which means
                    // that CTM^-1^T * N' is equivalent to N'^T*CTM^-1, which can be calculated with
                    // two dot products if the CTM inverse is uploaded to the GPU.

                    // We add epsilon so that rectangular corners are not degenerate, and circular
                    // corners remain unmodified. This only slightly increases inaccuracy for
                    // elliptical corners.
                    float sx = (scale.y + SK_ScalarNearlyZero) / (scale.x + SK_ScalarNearlyZero);
                    // Needed to calculate intermediate W of transformed normal.
                    float px = cornerMapping.y*cornerPt.y - cornerMapping.w*cornerPt.x;
                    float py = cornerMapping.z*cornerPt.x - cornerMapping.x*cornerPt.y;
                    // Inverse CTM, presumably calculated once as a uniform
                    SkM44 inv;
                    SkAssertResult(m.invert(&inv));

                    SkV4 normX4 = { sx*cornerMapping.w*fNormal.x,
                                   -sx*cornerMapping.y*fNormal.x,
                                   0.f,
                                   sx*px*fNormal.x};
                    SkV4 normY4 = {-cornerMapping.z*fNormal.y,
                                    cornerMapping.x*fNormal.y,
                                   0.f,
                                   py*fNormal.y};

                    SkV2 normX = {inv.col(0).dot(normX4), inv.col(1).dot(normX4)};
                    SkV2 normY = {inv.col(0).dot(normY4), inv.col(1).dot(normY4)};

                    if (joinScale == kMiterScale && fNormal.x > 0.f && fNormal.y > 0.f) {
                        // normX and normY represent adjacent edges' normals, so if we normalize
                        // them before adding together, we'll have a vector that bisects the edge
                        // normals instead of a vector matching fNormal, which is what we want when
                        // we're at a miter corner.
                        normX = normX.normalize();
                        normY = normY.normalize();
                        if (normX.dot(normY) < -0.8) {
                            // Nearly opposite directions, so the sum could have cancellation, so
                            // instead bisect orthogonal vectors and flip to keep consistent
                            float sign = normX.cross(normY) >= 0.f ? 1.f : -1.f;
                            normX = sign*SkV2{-normX.y, normX.x};
                            normY = sign*SkV2{normY.y, -normY.x};
                        }
                    }

                    devNorm = (normX + normY).normalize();
                }

                // The local coordinates for a device-space AA outset are clamped to the non-outset
                // point, which means we don't care about remaining in the same pre-homogenous
                // divide plane. This makes it very easy to determine a homogenous coordinate that
                // projects to the correct device-space position.
                devPos.x += devPos.w * kAARadius * devNorm.x;
                devPos.y += devPos.w * kAARadius * devNorm.y;
            }

            return SkV3{devPos.x, devPos.y, devPos.w};
        }
    }
};

static constexpr float kHR2 = SK_ScalarRoot2Over2; // "half root 2"

static constexpr LocalCornerVert kCornerTemplate[19] = {
    // Stroke-scale should be -1, 0, or 1.
    // Mirror-scale should be 0 or 1.
    // Center-weight should be -2 to never snap to center, -1 to snap when stroke coords would
    //     overlap, and 0 to snap for fill-style or overlapping coords.
    // Local-aa-scale should be 0 or 1.

    //  position,       normal,   stroke-scale   mirror-scale   center-weight
    // Device-space AA outsets from outer curve
    { {0.0f, 1.0f}, { 0.0f,  1.0f},  1.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  1.0f},  1.0f,          1.0f,           -2.f  },
    { {0.0f, 1.0f}, { kHR2,  kHR2},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { kHR2,  kHR2},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 1.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 1.0f,  0.0f},  1.0f,          0.0f,           -2.f  },

    // Outer anchors (no local or device-space normal outset)
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  1.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  1.0f,          0.0f,           -2.f  },

    // Center of stroke (equivalent to outer anchors when filling)
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  0.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  0.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  0.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  0.0f,          0.0f,           -2.f  },

    // Inner AA insets from inner curve
    { {0.0f, 1.0f}, { 0.0f, -1.0f}, -1.0f,          0.0f,           -1.f  },
    { {0.5f, 0.5f}, {-kHR2, -kHR2}, -1.0f,          1.0f,           -1.f  },
    { {1.0f, 0.0f}, {-1.0f,  0.0f}, -1.0f,          0.0f,           -1.f  },

    // Center filling vertices (equal to inner AA insets unless center-weight = 1)
    { {0.5f, 0.5f}, {-kHR2, -kHR2}, -1.0f,          1.0f,            0.f  },
    { {1.0f, 0.0f}, {-1.0f,  0.0f}, -1.0f,          0.0f,            0.f  },
};

static void compute_corner(SkV3 devPts[19], const SkM44& m, const SkV4& cornerMapping,
                           const SkV2& cornerPt, const SkV2& cornerRadii, const SkV4& center,
                           float centerWeight, float localAARadius, float strokeRadius,
                           SkPaint::Join join) {
    float joinScale;

    // TODO: checking against localAARadius can snap to rect corner unexpectedly under high skew
    // because localAARadius gets so big, but would be nice to be fuzzy here.
    if (cornerRadii.x <= 0.f || cornerRadii.y <= 0.f) {
        // Effectively a rectangular corner
        joinScale = kMiterScale; // default for rect corners
        if (strokeRadius > 0.f) {
            // Non-hairline strokes need to adjust the join scale factor to match style.
            if (join == SkPaint::kBevel_Join) {
                joinScale = kBevelScale;
            } else if (join == SkPaint::kRound_Join) {
                joinScale = kRoundScale;
            }
        }
    } else {
        // Rounded filled corner vertices are always positioned for a round join since the
        // underlying geometry has no real tangent discontinuity.
        joinScale = kRoundScale;
    }

    for (size_t i = 0; i < SK_ARRAY_COUNT(kCornerTemplate); ++i) {
        devPts[i] = kCornerTemplate[i].transform(m, cornerMapping, cornerPt, cornerRadii,
                                                 center, centerWeight, strokeRadius, joinScale,
                                                 localAARadius);
    }
}

static const uint16_t kBR = 0*SK_ARRAY_COUNT(kCornerTemplate);
static const uint16_t kTR = 1*SK_ARRAY_COUNT(kCornerTemplate);
static const uint16_t kTL = 2*SK_ARRAY_COUNT(kCornerTemplate);
static const uint16_t kBL = 3*SK_ARRAY_COUNT(kCornerTemplate);
static const size_t kVertexCount = 4*SK_ARRAY_COUNT(kCornerTemplate);
static void compute_vertices(SkV3 devPts[kVertexCount],
                             const SkM44& m,
                             const SkRRect& rrect,
                             float strokeRadius,
                             SkPaint::Join join) {
    SkV4 devCenter = m.map(rrect.getBounds().centerX(), rrect.getBounds().centerY(), 0.f, 1.f);

    float localAARadius = std::max({
            local_aa_radius(m, {rrect.getBounds().fRight, rrect.getBounds().fBottom}),
            local_aa_radius(m, {rrect.getBounds().fRight, rrect.getBounds().fTop}),
            local_aa_radius(m, {rrect.getBounds().fLeft, rrect.getBounds().fTop}),
            local_aa_radius(m, {rrect.getBounds().fLeft, rrect.getBounds().fBottom})
        });

    float centerWeight = 0.f; // No center snapping
    if (strokeRadius < 0.f) {
        // A fill, so inner vertices need to snap to the center and then adjust the stroke radius
        // to 0 for later math to work out nicely.
        strokeRadius = 0.f;
        centerWeight = 1.f;
    }

    // Check if the inset amount (max stroke-radius + local-aa-radius) would interfere with the
    // opposite edge's inset or interfere with the adjacent corner's curve. When this happens, snap
    // all the interior vertices to the center and let the fragment shader work through it.
    // TODO: Could force centerWeight = 2 for filled rects and quads for simplicity around non
    // orthogonal inset overlap calculations.
    float maxInset = strokeRadius + localAARadius;
    if (maxInset >= rrect.width() - maxInset || // L/R stroke insets would cross over
        maxInset >= rrect.height() - maxInset || // T/B stroke insets would cross over
        maxInset >= rrect.width() - rrect.radii(SkRRect::kLowerLeft_Corner).fX || // X corner cross
        maxInset >= rrect.width() - rrect.radii(SkRRect::kLowerRight_Corner).fX ||
        maxInset >= rrect.width() - rrect.radii(SkRRect::kUpperLeft_Corner).fX ||
        maxInset >= rrect.width() - rrect.radii(SkRRect::kUpperRight_Corner).fX ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kLowerLeft_Corner).fY || // Y corner cross
        maxInset >= rrect.height() - rrect.radii(SkRRect::kLowerRight_Corner).fY ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kUpperLeft_Corner).fY ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kUpperRight_Corner).fY) {
        // All interior vertices need to snap to the center
        centerWeight = 2.f;
    }

    // The normalized corner template is defined relative to the quarter circle with positive X
    // and positive Y, with a counter clockwise winding (if +Y points down). This corresponds to
    // the bottom-right corner.
    static constexpr SkV4 kBRBasis = { 1.f,  0.f,  0.f,  1.f};
    static constexpr SkV4 kTRBasis = { 0.f,  1.f, -1.f,  0.f};
    static constexpr SkV4 kTLBasis = {-1.f,  0.f,  0.f, -1.f};
    static constexpr SkV4 kBLBasis = { 0.f, -1.f,  1.f,  0.f};

    compute_corner(devPts + kBR, m, kBRBasis,
                   {rrect.getBounds().fRight,
                    rrect.getBounds().fBottom},
                   {rrect.radii(SkRRect::kLowerRight_Corner).fX,
                    rrect.radii(SkRRect::kLowerRight_Corner).fY},
                   devCenter, centerWeight, localAARadius, strokeRadius, join);
    compute_corner(devPts + kTR, m, kTRBasis,
                   {rrect.getBounds().fRight,
                    rrect.getBounds().fTop},
                   {rrect.radii(SkRRect::kUpperRight_Corner).fY,
                    rrect.radii(SkRRect::kUpperRight_Corner).fX},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
    compute_corner(devPts + kTL, m, kTLBasis,
                   {rrect.getBounds().fLeft,
                    rrect.getBounds().fTop},
                   {rrect.radii(SkRRect::kUpperLeft_Corner).fX,
                    rrect.radii(SkRRect::kUpperLeft_Corner).fY},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
    compute_corner(devPts + kBL, m, kBLBasis,
                   {rrect.getBounds().fLeft,
                    rrect.getBounds().fBottom},
                   {rrect.radii(SkRRect::kLowerLeft_Corner).fY,
                    rrect.radii(SkRRect::kLowerLeft_Corner).fX},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
}

// All indices
static const uint16_t kIndices[] = {
    // Exterior AA ramp outset
    kBR+0,kBR+6,kBR+1,kBR+7,kBR+2,kBR+8,kBR+3,kBR+8,kBR+4,kBR+9,kBR+5,kBR+9,
    kTR+0,kTR+6,kTR+1,kTR+7,kTR+2,kTR+8,kTR+3,kTR+8,kTR+4,kTR+9,kTR+5,kTR+9,
    kTL+0,kTL+6,kTL+1,kTL+7,kTL+2,kTL+8,kTL+3,kTL+8,kTL+4,kTL+9,kTL+5,kTL+9,
    kBL+0,kBL+6,kBL+1,kBL+7,kBL+2,kBL+8,kBL+3,kBL+8,kBL+4,kBL+9,kBL+5,kBL+9,
    kBR+0,kBR+6,kBR+6, // close and extra vertex to jump to next strip
    // Outer to central curve
    kBR+6,kBR+10,kBR+7,kBR+11,kBR+8,kBR+12,kBR+9,kBR+13,
    kTR+6,kTR+10,kTR+7,kTR+11,kTR+8,kTR+12,kTR+9,kTR+13,
    kTL+6,kTL+10,kTL+7,kTL+11,kTL+8,kTL+12,kTL+9,kTL+13,
    kBL+6,kBL+10,kBL+7,kBL+11,kBL+8,kBL+12,kBL+9,kBL+13,
    kBR+6,kBR+10,kBR+10, // close and extra vertex to jump to next strip
    // Center to inner curve's insets
    kBR+10,kBR+14,kBR+11,kBR+15,kBR+12,kBR+16,kBR+13,kBR+16,
    kTR+10,kTR+14,kTR+11,kTR+15,kTR+12,kTR+16,kTR+13,kTR+16,
    kTL+10,kTL+14,kTL+11,kTL+15,kTL+12,kTL+16,kTL+13,kTL+16,
    kBL+10,kBL+14,kBL+11,kBL+15,kBL+12,kBL+16,kBL+13,kBL+16,
    kBR+10,kBR+14,kBR+14, // close and extra vertex to jump to next strip
    // Inner inset to center of shape
    kBR+14,kBR+17,kBR+15,kBR+17,kBR+16,kBR+16,kBR+18,kTR+14,
    kTR+14,kTR+17,kTR+15,kTR+17,kTR+16,kTR+16,kTR+18,kTL+14,
    kTL+14,kTL+17,kTL+15,kTL+17,kTL+16,kTL+16,kTL+18,kBL+14,
    kBL+14,kBL+17,kBL+15,kBL+17,kBL+16,kBL+16,kBL+18,kBR+14 // close
};

// Separated to draw with different colors (vs. duplicating vertices to change colors).
static const uint16_t kOuterCornerIndices[] = {
    kBR+0,  kBR+0,kBR+6,kBR+1,kBR+7,kBR+2,kBR+8,kBR+3,kBR+8,kBR+4,kBR+9,kBR+5,  kBR+5,
    kTR+0,  kTR+0,kTR+6,kTR+1,kTR+7,kTR+2,kTR+8,kTR+3,kTR+8,kTR+4,kTR+9,kTR+5,  kTR+5,
    kTL+0,  kTL+0,kTL+6,kTL+1,kTL+7,kTL+2,kTL+8,kTL+3,kTL+8,kTL+4,kTL+9,kTL+5,  kTL+5,
    kBL+0,  kBL+0,kBL+6,kBL+1,kBL+7,kBL+2,kBL+8,kBL+3,kBL+8,kBL+4,kBL+9,kBL+5,  kBL+5,

    kBR+6,  kBR+6,kBR+10,kBR+7,kBR+11,kBR+8,kBR+12,kBR+9,kBR+13,  kBR+13,
    kTR+6,  kTR+6,kTR+10,kTR+7,kTR+11,kTR+8,kTR+12,kTR+9,kTR+13,  kTR+13,
    kTL+6,  kTL+6,kTL+10,kTL+7,kTL+11,kTL+8,kTL+12,kTL+9,kTL+13,  kTL+13,
    kBL+6,  kBL+6,kBL+10,kBL+7,kBL+11,kBL+8,kBL+12,kBL+9,kBL+13,  kBL+13
};

static const uint16_t kInnerCornerIndices[] = {
    kBR+10,  kBR+10,kBR+14,kBR+11,kBR+15,kBR+12,kBR+16,kBR+13,  kBR+13,
    kTR+10,  kTR+10,kTR+14,kTR+11,kTR+15,kTR+12,kTR+16,kTR+13,  kTR+13,
    kTL+10,  kTL+10,kTL+14,kTL+11,kTL+15,kTL+12,kTL+16,kTL+13,  kTL+13,
    kBL+10,  kBL+10,kBL+14,kBL+11,kBL+15,kBL+12,kBL+16,kBL+13,  kBL+13,
};

static const uint16_t kInteriorIndices[] = {
    kBR+14,kBR+17,kBR+15,kBR+17,kBR+16,kBR+16,kBR+18,kTR+14,
    kTR+14,kTR+17,kTR+15,kTR+17,kTR+16,kTR+16,kTR+18,kTL+14,
    kTL+14,kTL+17,kTL+15,kTL+17,kTL+16,kTL+16,kTL+18,kBL+14,
    kBL+14,kBL+17,kBL+15,kBL+17,kBL+16,kBL+16,kBL+18,kBR+14 // close
};

// Implicit in the original mesh from the tri-strip connections between corners
static const uint16_t kEdgeIndices[] = {
    kBR+5,   kBR+5,kBR+9,kTR+0,kTR+6,      kTR+6,
    kBR+9,   kBR+9,kBR+13,kTR+6,kTR+10,    kTR+10,
    kBR+13,  kBR+13,kBR+16,kTR+10,kTR+14,  kTR+14,

    kTR+5,   kTR+5,kTR+9,kTL+0,kTL+6,      kTL+6,
    kTR+9,   kTR+9,kTR+13,kTL+6,kTL+10,    kTL+10,
    kTR+13,  kTR+13,kTR+16,kTL+10,kTL+14,  kTL+14,

    kTL+5,   kTL+5,kTL+9,kBL+0,kBL+6,      kBL+6,
    kTL+9,   kTL+9,kTL+13,kBL+6,kBL+10,    kBL+10,
    kTL+13,  kTL+13,kTL+16,kBL+10,kBL+14,  kBL+14,

    kBL+5,   kBL+5,kBL+9,kBR+0,kBR+6,      kBR+6,
    kBL+9,   kBL+9,kBL+13,kBR+6,kBR+10,    kBR+10,
    kBL+13,  kBL+13,kBL+16,kBR+10,kBR+14,  kBR+14,
};

class GraphitePrimitivesSample : public Sample {
    static constexpr float kControlPointRadius = 3.f;
    static constexpr float kBaseScale = 50.f;
public:
    GraphitePrimitivesSample()
        : fOrigin{300.f, 300.f}
        , fXAxisPoint{300.f + kBaseScale, 300.f}
        , fYAxisPoint{300.f, 300.f + kBaseScale}
        , fStrokeWidth{10.f}
        , fJoinMode(SkPaint::kMiter_Join)
        , fMode(PrimitiveMode::kFillRect) {}

    void onDrawContent(SkCanvas* canvas) override {
        canvas->save();
        SkM44 viewMatrix = canvas->getLocalToDevice();

        canvas->concat(this->basisMatrix());

        SkM44 totalMatrix = canvas->getLocalToDevice();

            // Base shape + style
            SkRRect rrect = this->primitiveShape();
            canvas->drawRRect(rrect, paint(SK_ColorBLUE, this->strokeWidth(), fJoinMode));
        canvas->restore();

        canvas->save();
        canvas->resetMatrix();
            // Draw the full mesh directly in device space
            this->drawVertices(canvas, totalMatrix);
            // Draw the controls in device space so we get consistent circles for the click points.
            SkV4 origin = viewMatrix.map(fOrigin.x, fOrigin.y, 0.f, 1.f);
            SkV4 xAxis = viewMatrix.map(fXAxisPoint.x, fXAxisPoint.y, 0.f, 1.f);
            SkV4 yAxis = viewMatrix.map(fYAxisPoint.x, fYAxisPoint.y, 0.f, 1.f);

            // Axes
            canvas->drawLine({origin.x/origin.w, origin.y/origin.w},
                             {xAxis.x/xAxis.w, xAxis.y/xAxis.w}, paint(SK_ColorRED, 0.f));
            canvas->drawLine({origin.x/origin.w, origin.y/origin.w},
                             {yAxis.x/yAxis.w, yAxis.y/yAxis.w}, paint(SK_ColorGREEN, 0.f));

            // Control points
            canvas->drawCircle({origin.x/origin.w, origin.y/origin.w},
                               kControlPointRadius, paint(SK_ColorBLACK));
            canvas->drawCircle({xAxis.x/xAxis.w, xAxis.y/xAxis.w},
                               kControlPointRadius, paint(SK_ColorRED));
            canvas->drawCircle({yAxis.x/yAxis.w, yAxis.y/yAxis.w},
                               kControlPointRadius, paint(SK_ColorGREEN));
        canvas->restore();
    }

    Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
    bool onClick(Sample::Click*) override;
    bool onChar(SkUnichar) override;
    SkString name() override { return SkString("GraphitePrimitives"); }

private:
    class Click;

    enum class PrimitiveMode {
        kFillRect,
        kFillRRect,
        kStrokeRect,
        kStrokeRRect
    };

    // Computed from 3 control points. Concat with CTM to get total matrix.
    SkM44 basisMatrix() const {
        SkV2 xAxis = (fXAxisPoint - fOrigin) / kBaseScale;
        SkV2 yAxis = (fYAxisPoint - fOrigin) / kBaseScale;

        return SkM44::Cols({xAxis.x, xAxis.y, 0.f, 0.f},
                           {yAxis.x, yAxis.y, 0.f, 0.f},
                           {0.f, 0.f, 1.f, 0.f},
                           {fOrigin.x, fOrigin.y, 0.f, 1.f});
    }

    float strokeWidth() const {
        if (fMode == PrimitiveMode::kFillRect || fMode == PrimitiveMode::kFillRRect) {
            return -1.f;
        }
        return fStrokeWidth;
    }

    SkRRect primitiveShape() const {
        static const SkRect kOuterBounds = SkRect::MakeLTRB(-kBaseScale, -kBaseScale,
                                                            kBaseScale, kBaseScale);
        // Filled rounded rects can have arbitrary corners
        static const SkVector kOuterRadii[4] = { { 0.25f * kBaseScale, 0.75f * kBaseScale },
                                                 { 0.f, 0.f},
                                                 { 0.5f * kBaseScale, 0.5f * kBaseScale },
                                                 { 0.75f * kBaseScale, 0.25f * kBaseScale } };
        // // Stroked rounded rects will only have circular corners
        static const SkVector kStrokeRadii[4] = { { 0.25f * kBaseScale, 0.25f * kBaseScale },
                                                  { 0.f, 0.f },
                                                  { 0.5f * kBaseScale, 0.5f * kBaseScale },
                                                  { 0.75f * kBaseScale, 0.75f * kBaseScale } };

        float strokeRadius = 0.5f * fStrokeWidth;
        switch(fMode) {
            case PrimitiveMode::kFillRect:
                return SkRRect::MakeRect(kOuterBounds.makeOutset(strokeRadius, strokeRadius));
            case PrimitiveMode::kFillRRect: {
                SkRRect rrect;
                rrect.setRectRadii(kOuterBounds, kOuterRadii);
                rrect.outset(strokeRadius, strokeRadius);
                return rrect; }
            case PrimitiveMode::kStrokeRect:
                return SkRRect::MakeRect(kOuterBounds);
            case PrimitiveMode::kStrokeRRect: {
                SkRRect rrect;
                rrect.setRectRadii(kOuterBounds, kStrokeRadii);
                return rrect;
            }
        }

        SkUNREACHABLE;
    }

    void drawVertices(SkCanvas* canvas, const SkM44& ctm) {
        SkRRect rrect = this->primitiveShape();
        float strokeRadius = 0.5f * this->strokeWidth();

        SkV3 points[kVertexCount];
        SkPoint vertices[kVertexCount];
        compute_vertices(points, ctm, rrect, strokeRadius, fJoinMode);
        // SkCanvas::drawVertices() wants SkPoint, but normally we'd let the GPU handle the
        // perspective division and clipping.
        for (size_t i = 0; i < kVertexCount; ++i) {
            vertices[i] = SkPoint{points[i].x/points[i].z, points[i].y/points[i].z};
        }

        auto drawMeshSubset = [vertices, canvas](SkColor color,
                                                 const uint16_t* indices,
                                                 size_t indexCount) {
            sk_sp<SkVertices> mesh = SkVertices::MakeCopy(
                    SkVertices::kTriangleStrip_VertexMode, kVertexCount, vertices,
                    nullptr, nullptr, (int) indexCount, indices);
            SkPaint meshPaint;
            meshPaint.setColor(color);
            meshPaint.setAlphaf(0.5f);
            canvas->drawVertices(mesh, SkBlendMode::kSrc, meshPaint);
        };
        if (fColorize) {
            drawMeshSubset(SK_ColorGRAY,
                           kEdgeIndices,
                           SK_ARRAY_COUNT(kEdgeIndices));
            drawMeshSubset(SK_ColorDKGRAY,
                           kInteriorIndices,
                           SK_ARRAY_COUNT(kInteriorIndices));
            drawMeshSubset(SK_ColorMAGENTA,
                           kInnerCornerIndices,
                           SK_ARRAY_COUNT(kInnerCornerIndices));
            drawMeshSubset(SK_ColorCYAN,
                           kOuterCornerIndices,
                           SK_ARRAY_COUNT(kOuterCornerIndices));
        } else {
            drawMeshSubset(SK_ColorGRAY, kIndices, SK_ARRAY_COUNT(kIndices));
        }

        // Draw the edges over the triangle strip mesh, but keep track of edges already drawn so
        // that we don't oversaturate AA on edges shared by multiple triangles.
        std::unordered_set<uint32_t> edges;
        auto drawEdge = [&edges, vertices, canvas](uint16_t e0, uint16_t e1) {
            uint32_t edgeID = (std::max(e0, e1) << 16) | std::min(e0, e1);
            if (edges.find(edgeID) == edges.end()) {
                edges.insert(edgeID);
                if (SkScalarNearlyEqual(vertices[e0].fX, vertices[e1].fX) &&
                    SkScalarNearlyEqual(vertices[e0].fY, vertices[e1].fY)) {
                    return;
                }
                canvas->drawLine(vertices[e0], vertices[e1], paint(SK_ColorBLACK, 0.f));
            }
        };
        for (size_t i = 2; i < SK_ARRAY_COUNT(kIndices); ++i) {
            drawEdge(kIndices[i-1], kIndices[i]);
            drawEdge(kIndices[i-2], kIndices[i]);
        }
    }

    // This Sample is responsive to the entire transform of the viewer slide, including the
    // transform (rotation, scale, and perspective) selected from the widget. The 3 points below
    // define the location and basis of the local coordinate space, relative to the viewer's
    // coordinate space. This is used instead of the root canvas coordinate space because it aligns
    // with the coordinate space that the click handler operates in.
    SkV2 fOrigin;
    SkV2 fXAxisPoint;
    SkV2 fYAxisPoint;

    float fStrokeWidth;
    SkPaint::Join fJoinMode;
    PrimitiveMode fMode;
    bool fColorize = true;
};

class GraphitePrimitivesSample::Click : public Sample::Click {
public:
    Click(SkV2* point) : fPoint(point) {}

    void drag() {
        SkVector delta = fCurr - fPrev;
        *fPoint += {delta.fX, delta.fY};
    }

private:
    SkV2* fPoint;
};

Sample::Click* GraphitePrimitivesSample::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
    auto selected = [x,y](const SkV2& p) {
        return ((p - SkV2{x,y}).length() < kControlPointRadius);
    };

    if (selected(fOrigin)) {
        return new Click(&fOrigin);
    } else if (selected(fXAxisPoint)) {
        return new Click(&fXAxisPoint);
    } else if (selected(fYAxisPoint)) {
        return new Click(&fYAxisPoint);
    } else {
        return nullptr;
    }
}

bool GraphitePrimitivesSample::onClick(Sample::Click* click) {
    Click* myClick = (Click*) click;
    myClick->drag();
    return true;
}

bool GraphitePrimitivesSample::onChar(SkUnichar code) {
        switch(code) {
            case '1':
                fMode = PrimitiveMode::kFillRect;
                return true;
            case '2':
                fMode = PrimitiveMode::kFillRRect;
                return true;
            case '3':
                fMode = PrimitiveMode::kStrokeRect;
                return true;
            case '4':
                fMode = PrimitiveMode::kStrokeRRect;
                return true;
            case '-':
                fStrokeWidth = std::max(0.f, fStrokeWidth - 0.4f);
                return true;
            case '=':
                fStrokeWidth = std::min(5 * kBaseScale, fStrokeWidth + 0.4f);
                return true;
            case 'q':
                fJoinMode = SkPaint::kRound_Join;
                return true;
            case 'w':
                fJoinMode = SkPaint::kBevel_Join;
                return true;
            case 'e':
                fJoinMode = SkPaint::kMiter_Join;
                return true;
            case 'r':
                fStrokeWidth = 10.f;
                fOrigin = {300.f, 300.f};
                fXAxisPoint = {300.f + kBaseScale, 300.f};
                fYAxisPoint = {300.f, 300.f + kBaseScale};
                return true;
            case 'c':
                fColorize = !fColorize;
                return true;
        }
        return false;
}

DEF_SAMPLE(return new GraphitePrimitivesSample();)
