/*
 * 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 "SkRRectPriv.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] * SkRRectPriv::GetSimpleRadii(fRRect).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;)
}
