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

#include "gm.h"
#include "sk_tool_utils.h"
#include "SkAnimTimer.h"
#include "SkBlurMaskFilter.h"
#include "SkRRectsGaussianEdgeMaskFilter.h"
#include "SkPath.h"
#include "SkPathOps.h"
#include "SkRRect.h"
#include "SkStroke.h"

constexpr int kNumCols = 2;
constexpr int kNumRows = 5;
constexpr int kCellSize = 128;
constexpr SkScalar kPad = 8.0f;
constexpr SkScalar kInitialBlurRadius = 8.0f;
constexpr SkScalar kPeriod = 8.0f;
constexpr int kClipOffset = 32;

///////////////////////////////////////////////////////////////////////////////////////////////////

class Object {
public:
    virtual ~Object() {}
    // When it returns true, this call will have placed a device-space _circle, rect or
    // simple circular_ RRect in "rr"
    virtual bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const = 0;
    virtual SkPath asPath(SkScalar inset) const = 0;
    virtual void draw(SkCanvas* canvas, const SkPaint& paint) const = 0;
    virtual void clip(SkCanvas* canvas) const = 0;
    virtual bool contains(const SkRect& r) const = 0;
    virtual const SkRect& bounds() const = 0;
};

typedef Object* (*PFMakeMthd)(const SkRect& r);

class RRect : public Object {
public:
    RRect(const SkRect& r) {
        fRRect = SkRRect::MakeRectXY(r, 4*kPad, 4*kPad);
    }

    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
        if (!ctm.isSimilarity()) { // the corners have to remain circular
            return false;
        }

        SkScalar scales[2];
        if (!ctm.getMinMaxScales(scales)) {
            return false;
        }

        SkASSERT(SkScalarNearlyEqual(scales[0], scales[1]));

        SkRect devRect;
        ctm.mapRect(&devRect, fRRect.rect());

        SkScalar scaledRad = scales[0] * fRRect.getSimpleRadii().fX;

        *rr = SkRRect::MakeRectXY(devRect, scaledRad, scaledRad);
        return true;
    }

    SkPath asPath(SkScalar inset) const override {
        SkRRect tmp = fRRect;
        tmp.inset(inset, inset);
        SkPath p;
        p.addRRect(tmp);
        return p;
    }

    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
        canvas->drawRRect(fRRect, paint);
    }

    void clip(SkCanvas* canvas) const override {
        canvas->clipRRect(fRRect);
    }

    bool contains(const SkRect& r) const override {
        return fRRect.contains(r);
    }

    const SkRect& bounds() const override {
        return fRRect.getBounds();
    }

    static Object* Make(const SkRect& r) {
        return new RRect(r);
    }

private:
    SkRRect  fRRect;
};

class StrokedRRect : public Object {
public:
    StrokedRRect(const SkRect& r) {
        fRRect = SkRRect::MakeRectXY(r, 2*kPad, 2*kPad);
        fStrokedBounds = r.makeOutset(kPad, kPad);
    }

    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
        return false;
    }

    SkPath asPath(SkScalar inset) const override {
        SkRRect tmp = fRRect;
        tmp.inset(inset, inset);

        // In this case we want the outline of the stroked rrect
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(kPad);

        SkPath p, stroked;
        p.addRRect(tmp);
        SkStroke stroke(paint);
        stroke.strokePath(p, &stroked);
        return stroked;
    }

    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
        SkPaint stroke(paint);
        stroke.setStyle(SkPaint::kStroke_Style);
        stroke.setStrokeWidth(kPad);

        canvas->drawRRect(fRRect, stroke);
    }

    void clip(SkCanvas* canvas) const override {
        canvas->clipPath(this->asPath(0.0f));
    }

    bool contains(const SkRect& r) const override {
        return false;
    }

    const SkRect& bounds() const override {
        return fStrokedBounds;
    }

    static Object* Make(const SkRect& r) {
        return new StrokedRRect(r);
    }

private:
    SkRRect  fRRect;
    SkRect   fStrokedBounds;
};

class Oval : public Object {
public:
    Oval(const SkRect& r) {
        fRRect = SkRRect::MakeOval(r);
    }

    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
        if (!ctm.isSimilarity()) { // circles have to remain circles
            return false;
        }

        SkRect devRect;
        ctm.mapRect(&devRect, fRRect.rect());
        *rr = SkRRect::MakeOval(devRect);
        return true;
    }

    SkPath asPath(SkScalar inset) const override {
        SkRRect tmp = fRRect;
        tmp.inset(inset, inset);

        SkPath p;
        p.addRRect(tmp);
        return p;
    }

    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
        canvas->drawRRect(fRRect, paint);
    }

    void clip(SkCanvas* canvas) const override {
        canvas->clipRRect(fRRect);
    }

    bool contains(const SkRect& r) const override {
        return fRRect.contains(r);
    }

    const SkRect& bounds() const override {
        return fRRect.getBounds();
    }

    static Object* Make(const SkRect& r) {
        return new Oval(r);
    }

private:
    SkRRect  fRRect;
};

class Rect : public Object {
public:
    Rect(const SkRect& r) : fRect(r) { }

    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
        if (!ctm.rectStaysRect()) {
            return false;
        }

        SkRect devRect;
        ctm.mapRect(&devRect, fRect);
        *rr = SkRRect::MakeRect(devRect);
        return true;
    }

    SkPath asPath(SkScalar inset) const override {
        SkRect tmp = fRect;
        tmp.inset(inset, inset);

        SkPath p;
        p.addRect(tmp);
        return p;
    }

    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
        canvas->drawRect(fRect, paint);
    }

    void clip(SkCanvas* canvas) const override {
        canvas->clipRect(fRect);
    }

    bool contains(const SkRect& r) const override {
        return fRect.contains(r);
    }

    const SkRect& bounds() const override {
        return fRect;
    }

    static Object* Make(const SkRect& r) {
        return new Rect(r);
    }

private:
    SkRect  fRect;
};

class Pentagon : public Object {
public:
    Pentagon(const SkRect& r) {
        SkPoint points[5] = {
            {  0.000000f, -1.000000f },
            { -0.951056f, -0.309017f },
            { -0.587785f,  0.809017f },
            {  0.587785f,  0.809017f },
            {  0.951057f, -0.309017f },
        };

        SkScalar height = r.height()/2.0f;
        SkScalar width = r.width()/2.0f;

        fPath.moveTo(r.centerX() + points[0].fX * width, r.centerY() + points[0].fY * height);
        fPath.lineTo(r.centerX() + points[1].fX * width, r.centerY() + points[1].fY * height);
        fPath.lineTo(r.centerX() + points[2].fX * width, r.centerY() + points[2].fY * height);
        fPath.lineTo(r.centerX() + points[3].fX * width, r.centerY() + points[3].fY * height);
        fPath.lineTo(r.centerX() + points[4].fX * width, r.centerY() + points[4].fY * height);
        fPath.close();
    }

    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
        return false;
    }

    SkPath asPath(SkScalar inset) const override { return fPath; }

    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
        canvas->drawPath(fPath, paint);
    }

    void clip(SkCanvas* canvas) const override {
        canvas->clipPath(this->asPath(0.0f));
    }

    bool contains(const SkRect& r) const override {
        return false;
    }

    const SkRect& bounds() const override {
        return fPath.getBounds();
    }

    static Object* Make(const SkRect& r) {
        return new Pentagon(r);
    }

private:
    SkPath fPath;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
namespace skiagm {

// This GM attempts to mimic Android's reveal animation
class RevealGM : public GM {
public:
    enum Mode {
        kBlurMask_Mode,
        kRRectsGaussianEdge_Mode,

        kLast_Mode = kRRectsGaussianEdge_Mode
    };
    static const int kModeCount = kLast_Mode + 1;

    enum CoverageGeom {
        kRect_CoverageGeom,
        kRRect_CoverageGeom,
        kDRRect_CoverageGeom,
        kPath_CoverageGeom,

        kLast_CoverageGeom = kPath_CoverageGeom
    };
    static const int kCoverageGeomCount = kLast_CoverageGeom + 1;

    RevealGM()
        : fFraction(0.5f)
        , fMode(kRRectsGaussianEdge_Mode)
        , fPause(false)
        , fBlurRadius(kInitialBlurRadius)
        , fCoverageGeom(kRect_CoverageGeom) {
        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
    }

protected:
    bool runAsBench() const override { return true; }

    SkString onShortName() override {
        return SkString("reveal");
    }

    SkISize onISize() override {
        return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize);
    }

    void onDraw(SkCanvas* canvas) override {
        PFMakeMthd clipMakes[kNumCols] = { Oval::Make, Rect::Make };
        PFMakeMthd drawMakes[kNumRows] = {
            RRect::Make, StrokedRRect::Make, Oval::Make, Rect::Make, Pentagon::Make
        };

        SkPaint strokePaint;
        strokePaint.setStyle(SkPaint::kStroke_Style);
        strokePaint.setStrokeWidth(0.0f);

        for (int y = 0; y < kNumRows; ++y) {
            for (int x = 0; x < kNumCols; ++x) {
                SkRect cell = SkRect::MakeXYWH(SkIntToScalar(x*kCellSize),
                                               SkIntToScalar(y*kCellSize),
                                               SkIntToScalar(kCellSize),
                                               SkIntToScalar(kCellSize));

                canvas->save();
                canvas->clipRect(cell);

                cell.inset(kPad, kPad);
                SkPoint clipCenter = SkPoint::Make(cell.centerX() - kClipOffset,
                                                   cell.centerY() + kClipOffset);
                SkScalar curSize = kCellSize * fFraction;
                const SkRect clipRect = SkRect::MakeLTRB(clipCenter.fX - curSize,
                                                         clipCenter.fY - curSize,
                                                         clipCenter.fX + curSize,
                                                         clipCenter.fY + curSize);

                std::unique_ptr<Object> clipObj((*clipMakes[x])(clipRect));
                std::unique_ptr<Object> drawObj((*drawMakes[y])(cell));

                // The goal is to replace this clipped draw (which clips the
                // shadow) with a draw using the geometric clip
                if (kBlurMask_Mode == fMode) {
                    SkPath clippedPath;

                    SkScalar sigma = fBlurRadius / 4.0f;

                    if (clipObj->contains(drawObj->bounds())) {
                        clippedPath = drawObj->asPath(2.0f*sigma);
                    } else {
                        SkPath drawnPath = drawObj->asPath(2.0f*sigma);
                        SkPath clipPath  = clipObj->asPath(2.0f*sigma);

                        SkAssertResult(Op(clipPath, drawnPath, kIntersect_SkPathOp, &clippedPath));
                    }

                    SkPaint blurPaint;
                    blurPaint.setAntiAlias(true);
                    blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma));
                    canvas->drawPath(clippedPath, blurPaint);
                } else {
                    SkASSERT(kRRectsGaussianEdge_Mode == fMode);

                    SkRect cover = drawObj->bounds();
                    SkAssertResult(cover.intersect(clipObj->bounds()));

                    SkPaint paint;

                    SkRRect devSpaceClipRR, devSpaceDrawnRR;

                    if (clipObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceClipRR) &&
                        drawObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceDrawnRR)) {
                        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceClipRR,
                                                                                 devSpaceDrawnRR,
                                                                                 fBlurRadius));
                    }

                    strokePaint.setColor(SK_ColorBLUE);

                    switch (fCoverageGeom) {
                        case kRect_CoverageGeom:
                            canvas->drawRect(cover, paint);
                            canvas->drawRect(cover, strokePaint);
                            break;
                        case kRRect_CoverageGeom: {
                            const SkRRect rrect = SkRRect::MakeRectXY(
                                                                    cover.makeOutset(10.0f, 10.0f),
                                                                    10.0f, 10.0f);
                            canvas->drawRRect(rrect, paint);
                            canvas->drawRRect(rrect, strokePaint);
                            break;
                        }
                        case kDRRect_CoverageGeom: {
                            const SkRRect inner = SkRRect::MakeRectXY(cover.makeInset(10.0f, 10.0f),
                                                                      10.0f, 10.0f);
                            const SkRRect outer = SkRRect::MakeRectXY(
                                                                    cover.makeOutset(10.0f, 10.0f),
                                                                    10.0f, 10.0f);
                            canvas->drawDRRect(outer, inner, paint);
                            canvas->drawDRRect(outer, inner, strokePaint);
                            break;
                        }
                        case kPath_CoverageGeom: {
                            SkPath path;
                            path.moveTo(cover.fLeft, cover.fTop);
                            path.lineTo(cover.centerX(), cover.centerY());
                            path.lineTo(cover.fRight, cover.fTop);
                            path.lineTo(cover.fRight, cover.fBottom);
                            path.lineTo(cover.centerX(), cover.centerY());
                            path.lineTo(cover.fLeft, cover.fBottom);
                            path.close();
                            canvas->drawPath(path, paint);
                            canvas->drawPath(path, strokePaint);
                            break;
                        }
                    }
                }

                // Draw the clip and draw objects for reference
                strokePaint.setColor(SK_ColorRED);
                canvas->drawPath(drawObj->asPath(0.0f), strokePaint);
                strokePaint.setColor(SK_ColorGREEN);
                canvas->drawPath(clipObj->asPath(0.0f), strokePaint);

                canvas->restore();
            }
        }
    }

    bool onHandleKey(SkUnichar uni) override {
        switch (uni) {
            case 'C':
                fMode = (Mode)((fMode + 1) % kModeCount);
                return true;
            case '+':
                fBlurRadius += 1.0f;
                return true;
            case '-':
                fBlurRadius = SkTMax(1.0f, fBlurRadius - 1.0f);
                return true;
            case 'p':
                fPause = !fPause;
                return true;
            case 'G':
                fCoverageGeom = (CoverageGeom) ((fCoverageGeom+1) % kCoverageGeomCount);
                return true;
        }

        return false;
    }

    bool onAnimate(const SkAnimTimer& timer) override {
        if (!fPause) {
            fFraction = timer.pingPong(kPeriod, 0.0f, 0.0f, 1.0f);
        }
        return true;
    }

private:
    SkScalar     fFraction;
    Mode         fMode;
    bool         fPause;
    float        fBlurRadius;
    CoverageGeom fCoverageGeom;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new RevealGM;)
}
