/*
 * 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 "include/core/SkCanvas.h"
#include "include/core/SkPath.h"
#include "samplecode/Sample.h"

#include <iostream>
#include <cmath>

#define PI SK_ScalarPI

#define LIN_SEGMENTS 10

class OverstrokeView : public Sample {
   public:
    SkScalar fStroke;
    int fPathType;  // super lazy enum
    bool fClosePath;
    bool fDrawFillPath;
    bool fDumpHex;
    OverstrokeView() {
        fStroke = 5;
        fPathType = 0;
        fClosePath = false;
        fDrawFillPath = false;
        fDumpHex = false;
        this->setBGColor(0xFFFFFFFF);
    }

   protected:
    SkString name() override { return SkString("PathOverstroke"); }

    bool onChar(SkUnichar uni) override {
            switch (uni) {
                case ',':
                    fStroke += 1.0;
                    return true;
                case '.':
                    fStroke -= 1.0;
                    return true;
                case 'x':
                    fPathType = (fPathType + 1) % 4;
                    return true;
                case 'c':
                    fClosePath = !fClosePath;
                    return true;
                case 'f':
                    fDrawFillPath = !fDrawFillPath;
                    return true;
                case 'D':
                    fDumpHex = !fDumpHex;
                    return true;
                default:
                    break;
            }
            return false;
    }

    SkPath quadPath(SkPoint p1, SkPoint p2) {
        SkASSERT(p1.y() == p2.y());

        SkPath path;
        path.moveTo(p1);
        path.lineTo(p2);

        SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);

        path.quadTo(p3, p1);

        return path;
    }

    SkPath cubicPath(SkPoint p1, SkPoint p2) {
        SkASSERT(p1.y() == p2.y());

        SkPath path;
        path.moveTo(p1);

        SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f);
        SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f);

        path.cubicTo(p3, p4, p2);

        return path;
    }

    SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
        SkASSERT(p1.y() == p2.y());

        SkPath path;
        path.moveTo(p1);
        path.lineTo(p2);

        SkPoint pt;

        for (int i = 0; i < LIN_SEGMENTS; i++) {
            float theta = i * PI / (LIN_SEGMENTS);
            SkScalar x = 65 + 15 * cos(theta);
            SkScalar y = 50 - 15 * sin(theta);
            pt = SkPoint::Make(x, y);
            path.lineTo(pt);
        }
        path.lineTo(p1);

        return path;
    }

    SkPath rectPath(SkPoint p1) {
        SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
        SkPath path;
        path.addRect(r);

        return path;
    }

    void onDrawContent(SkCanvas* canvas) override {
        const float SCALE = 1;

        canvas->translate(30, 40);
        canvas->scale(SCALE, SCALE);

        SkPoint p1 = SkPoint::Make(50, 50);
        SkPoint p2 = SkPoint::Make(80, 50);

        SkPath path;
        switch (fPathType) {
            case 0:
                path = quadPath(p1, p2);
                break;
            case 1:
                path = cubicPath(p1, p2);
                break;
            case 2:
                path = rectPath(p1);
                break;
            case 3:
                path = linSemicirclePath(p1, p2);
                break;
            default:
                path = quadPath(p1, p2);
                break;
        }

        if (fClosePath) {
            path.close();
        }

        SkPaint p;
        p.setColor(SK_ColorRED);
        p.setAntiAlias(true);
        p.setStyle(SkPaint::kStroke_Style);
        p.setStrokeWidth(fStroke);

        canvas->drawPath(path, p);

        if (fDumpHex) {
            std::cerr << "path dumpHex" << std::endl;
            path.dumpHex();
        }

        SkPaint hairp;
        hairp.setColor(SK_ColorBLACK);
        hairp.setAntiAlias(true);
        hairp.setStyle(SkPaint::kStroke_Style);

        if (fDrawFillPath) {
            SkPath fillpath;
            p.getFillPath(path, &fillpath);

            canvas->drawPath(fillpath, hairp);

            if (fDumpHex) {
                std::cerr << "fillpath dumpHex" << std::endl;
                fillpath.dumpHex();
            }
        }

        if (fDumpHex) {
            std::cerr << std::endl;

            fDumpHex = false;
        }

        // draw original path with green hairline
        hairp.setColor(SK_ColorGREEN);
        canvas->drawPath(path, hairp);
    }

   private:
    using INHERITED = Sample;
};

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

DEF_SAMPLE( return new OverstrokeView(); )
