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

#include "sk_tool_utils.h"
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkImage.h"
#include "SkSurface.h"

#define FAT_PIXEL_COLOR     SK_ColorBLACK
#define PIXEL_CENTER_SIZE   3
#define WIRE_FRAME_COLOR    0xFFFF0000  /*0xFF00FFFF*/
#define WIRE_FRAME_SIZE     1.5f

static SkScalar apply_grid(SkScalar x) {
    const SkScalar grid = 2;
    return SkScalarRoundToScalar(x * grid) / grid;
}

static void apply_grid(SkPoint pts[], int count) {
    for (int i = 0; i < count; ++i) {
        pts[i].set(apply_grid(pts[i].fX), apply_grid(pts[i].fY));
    }
}

static void erase(SkSurface* surface) {
    surface->getCanvas()->clear(SK_ColorTRANSPARENT);
}

class FatBits {
public:
    FatBits() {
        fAA = false;
        fStyle = kHair_Style;
        fGrid = true;
        fShowSkeleton = true;
        fUseGPU = false;
        fUseClip = false;
        fRectAsOval = false;
        fUseTriangle = false;

        fClipRect.set(2, 2, 11, 8 );
    }

    int getZoom() const { return fZoom; }

    bool getAA() const { return fAA; }
    void setAA(bool aa) { fAA = aa; }

    bool getGrid() const { return fGrid; }
    void setGrid(bool g) { fGrid = g; }

    bool getShowSkeleton() const { return fShowSkeleton; }
    void setShowSkeleton(bool ss) { fShowSkeleton = ss; }

    bool getUseGPU() const { return fUseGPU; }
    void setUseGPU(bool ug) { fUseGPU = ug; }

    bool getTriangle() const { return fUseTriangle; }
    void setTriangle(bool ut) { fUseTriangle = ut; }

    void toggleRectAsOval() { fRectAsOval = !fRectAsOval; }

    bool getUseClip() const { return fUseClip; }
    void setUseClip(bool uc) { fUseClip = uc; }

    enum Style {
        kHair_Style,
        kStroke_Style,
    };
    Style getStyle() const { return fStyle; }
    void setStyle(Style s) { fStyle = s; }

    void setWHZ(int width, int height, int zoom) {
        fW = width;
        fH = height;
        fZoom = zoom;
        fBounds.set(0, 0, SkIntToScalar(width * zoom), SkIntToScalar(height * zoom));
        fMatrix.setScale(SkIntToScalar(zoom), SkIntToScalar(zoom));
        fInverse.setScale(SK_Scalar1 / zoom, SK_Scalar1 / zoom);
        fShader.reset(sk_tool_utils::create_checkerboard_shader(
                              0xFFCCCCCC, 0xFFFFFFFF, zoom));

        SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
        fMinSurface.reset(SkSurface::NewRaster(info));
        info = info.makeWH(width * zoom, height * zoom);
        fMaxSurface.reset(SkSurface::NewRaster(info));
    }

    void drawBG(SkCanvas*);
    void drawFG(SkCanvas*);
    void drawLine(SkCanvas*, SkPoint pts[2]);
    void drawRect(SkCanvas* canvas, SkPoint pts[2]);
    void drawTriangle(SkCanvas* canvas, SkPoint pts[3]);

private:
    bool fAA, fGrid, fShowSkeleton, fUseGPU, fUseClip, fRectAsOval, fUseTriangle;
    Style fStyle;
    int fW, fH, fZoom;
    SkMatrix fMatrix, fInverse;
    SkRect   fBounds, fClipRect;
    SkAutoTUnref<SkShader> fShader;
    SkAutoTUnref<SkSurface> fMinSurface;
    SkAutoTUnref<SkSurface> fMaxSurface;

    void setupPaint(SkPaint* paint) {
        bool aa = this->getAA();
        switch (fStyle) {
            case kHair_Style:
                paint->setStrokeWidth(0);
                break;
            case kStroke_Style:
                paint->setStrokeWidth(SK_Scalar1);
                break;
        }
        paint->setAntiAlias(aa);
    }

    void setupSkeletonPaint(SkPaint* paint) {
        paint->setStyle(SkPaint::kStroke_Style);
        paint->setStrokeWidth(WIRE_FRAME_SIZE);
        paint->setColor(fShowSkeleton ? WIRE_FRAME_COLOR : 0);
        paint->setAntiAlias(true);
    }

    void drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]);
    void drawLineSkeleton(SkCanvas* max, const SkPoint pts[]);
    void drawRectSkeleton(SkCanvas* max, const SkRect& r) {
        SkPaint paint;
        this->setupSkeletonPaint(&paint);
        SkPath path;

        if (fUseGPU && fAA) {
            SkRect rr = r;
            rr.inset(SkIntToScalar(fZoom)/2, SkIntToScalar(fZoom)/2);
            path.addRect(rr);
            path.moveTo(rr.fLeft, rr.fTop);
            path.lineTo(rr.fRight, rr.fBottom);
            rr = r;
            rr.inset(-SkIntToScalar(fZoom)/2, -SkIntToScalar(fZoom)/2);
            path.addRect(rr);
        } else {
            fRectAsOval ? path.addOval(r) : path.addRect(r);
            if (fUseGPU) {
                path.moveTo(r.fLeft, r.fTop);
                path.lineTo(r.fRight, r.fBottom);
            }
        }
        max->drawPath(path, paint);
    }

    void copyMinToMax() {
        erase(fMaxSurface);
        SkCanvas* canvas = fMaxSurface->getCanvas();
        canvas->save();
        canvas->concat(fMatrix);
        fMinSurface->draw(canvas, 0, 0, NULL);
        canvas->restore();

        SkPaint paint;
        paint.setXfermodeMode(SkXfermode::kClear_Mode);
        for (int iy = 1; iy < fH; ++iy) {
            SkScalar y = SkIntToScalar(iy * fZoom);
            canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
        }
        for (int ix = 1; ix < fW; ++ix) {
            SkScalar x = SkIntToScalar(ix * fZoom);
            canvas->drawLine(x - SK_ScalarHalf, 0, x - SK_ScalarHalf, 999, paint);
        }
    }
};

void FatBits::drawBG(SkCanvas* canvas) {
    SkPaint paint;

    paint.setShader(fShader);
    canvas->drawRect(fBounds, paint);
    paint.setShader(NULL);
}

void FatBits::drawFG(SkCanvas* canvas) {
    SkPaint inner, outer;

    inner.setAntiAlias(true);
    inner.setColor(SK_ColorBLACK);
    inner.setStrokeWidth(PIXEL_CENTER_SIZE);

    outer.setAntiAlias(true);
    outer.setColor(SK_ColorWHITE);
    outer.setStrokeWidth(PIXEL_CENTER_SIZE + 2);

    SkScalar half = SkIntToScalar(fZoom) / 2;
    for (int iy = 0; iy < fH; ++iy) {
        SkScalar y = SkIntToScalar(iy * fZoom) + half;
        for (int ix = 0; ix < fW; ++ix) {
            SkScalar x = SkIntToScalar(ix * fZoom) + half;

            canvas->drawPoint(x, y, outer);
            canvas->drawPoint(x, y, inner);
        }
    }

    if (fUseClip) {
        SkPaint p;
        p.setStyle(SkPaint::kStroke_Style);
        p.setColor(SK_ColorLTGRAY);
        SkRect r = {
            fClipRect.fLeft * fZoom,
            fClipRect.fTop * fZoom,
            fClipRect.fRight * fZoom,
            fClipRect.fBottom * fZoom
        };
        canvas->drawRect(r, p);
    }
}

void FatBits::drawLineSkeleton(SkCanvas* max, const SkPoint pts[]) {
    SkPaint paint;
    this->setupSkeletonPaint(&paint);

    SkPath path;
    path.moveTo(pts[0]);
    path.lineTo(pts[1]);

    switch (fStyle) {
        case kHair_Style:
            if (fUseGPU) {
                SkPaint p;
                p.setStyle(SkPaint::kStroke_Style);
                p.setStrokeWidth(SK_Scalar1 * fZoom);
                SkPath dst;
                p.getFillPath(path, &dst);
                path.addPath(dst);
            }
            break;
        case kStroke_Style: {
            SkPaint p;
            p.setStyle(SkPaint::kStroke_Style);
            p.setStrokeWidth(SK_Scalar1 * fZoom);
            SkPath dst;
            p.getFillPath(path, &dst);
            path = dst;

            if (fUseGPU) {
                path.moveTo(dst.getPoint(0));
                path.lineTo(dst.getPoint(2));
            }
        } break;
    }
    max->drawPath(path, paint);
}

void FatBits::drawLine(SkCanvas* canvas, SkPoint pts[]) {
    SkPaint paint;

    fInverse.mapPoints(pts, 2);

    if (fGrid) {
        apply_grid(pts, 2);
    }

    erase(fMinSurface);
    this->setupPaint(&paint);
    paint.setColor(FAT_PIXEL_COLOR);
    if (fUseClip) {
        fMinSurface->getCanvas()->save();
        SkRect r = fClipRect;
        r.inset(SK_Scalar1/3, SK_Scalar1/3);
        fMinSurface->getCanvas()->clipRect(r, SkRegion::kIntersect_Op, true);
    }
    fMinSurface->getCanvas()->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
    if (fUseClip) {
        fMinSurface->getCanvas()->restore();
    }
    this->copyMinToMax();

    SkCanvas* max = fMaxSurface->getCanvas();

    fMatrix.mapPoints(pts, 2);
    this->drawLineSkeleton(max, pts);

    fMaxSurface->draw(canvas, 0, 0, NULL);
}

void FatBits::drawRect(SkCanvas* canvas, SkPoint pts[2]) {
    SkPaint paint;

    fInverse.mapPoints(pts, 2);

    if (fGrid) {
        apply_grid(pts, 2);
    }

    SkRect r;
    r.set(pts, 2);

    erase(fMinSurface);
    this->setupPaint(&paint);
    paint.setColor(FAT_PIXEL_COLOR);
    {
        SkCanvas* c = fMinSurface->getCanvas();
        fRectAsOval ? c->drawOval(r, paint) : c->drawRect(r, paint);
    }
    this->copyMinToMax();

    SkCanvas* max = fMaxSurface->getCanvas();

    fMatrix.mapPoints(pts, 2);
    r.set(pts, 2);
    this->drawRectSkeleton(max, r);

    fMaxSurface->draw(canvas, 0, 0, NULL);
}

void FatBits::drawTriangleSkeleton(SkCanvas* max, const SkPoint pts[]) {
    SkPaint paint;
    this->setupSkeletonPaint(&paint);

    SkPath path;
    path.moveTo(pts[0]);
    path.lineTo(pts[1]);
    path.lineTo(pts[2]);
    path.close();

    max->drawPath(path, paint);
}

void FatBits::drawTriangle(SkCanvas* canvas, SkPoint pts[3]) {
    SkPaint paint;

    fInverse.mapPoints(pts, 3);

    if (fGrid) {
        apply_grid(pts, 3);
    }

    SkPath path;
    path.moveTo(pts[0]);
    path.lineTo(pts[1]);
    path.lineTo(pts[2]);
    path.close();

    erase(fMinSurface);
    this->setupPaint(&paint);
    paint.setColor(FAT_PIXEL_COLOR);
    fMinSurface->getCanvas()->drawPath(path, paint);
    this->copyMinToMax();

    SkCanvas* max = fMaxSurface->getCanvas();

    fMatrix.mapPoints(pts, 3);
    this->drawTriangleSkeleton(max, pts);

    fMaxSurface->draw(canvas, 0, 0, NULL);
}

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

class IndexClick : public SkView::Click {
    int fIndex;
public:
    IndexClick(SkView* v, int index) : SkView::Click(v), fIndex(index) {}

    static int GetIndex(SkView::Click* click) {
        return ((IndexClick*)click)->fIndex;
    }
};

class DrawLineView : public SampleView {
    FatBits fFB;
    SkPoint fPts[3];
    bool    fIsRect;
public:
    DrawLineView() {
        fFB.setWHZ(24, 16, 48);
        fPts[0].set(48, 48);
        fPts[1].set(48 * 5, 48 * 4);
        fPts[2].set(48 * 2, 48 * 6);
        fIsRect = false;
    }

    void setStyle(FatBits::Style s) {
        fFB.setStyle(s);
        this->inval(NULL);
    }

protected:
    bool onQuery(SkEvent* evt) SK_OVERRIDE {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "FatBits");
            return true;
        }
        SkUnichar uni;
        if (SampleCode::CharQ(*evt, &uni)) {
            switch (uni) {
                case 'c':
                    fFB.setUseClip(!fFB.getUseClip());
                    this->inval(NULL);
                    return true;
                case 'r':
                    fIsRect = !fIsRect;
                    this->inval(NULL);
                    return true;
                case 'o':
                    fFB.toggleRectAsOval();
                    this->inval(NULL);
                    return true;
                case 'x':
                    fFB.setGrid(!fFB.getGrid());
                    this->inval(NULL);
                    return true;
                case 's':
                    if (FatBits::kStroke_Style == fFB.getStyle()) {
                        this->setStyle(FatBits::kHair_Style);
                    } else {
                        this->setStyle(FatBits::kStroke_Style);
                    }
                    return true;
                case 'a':
                    fFB.setAA(!fFB.getAA());
                    this->inval(NULL);
                    return true;
                case 'w':
                    fFB.setShowSkeleton(!fFB.getShowSkeleton());
                    this->inval(NULL);
                    return true;
                case 'g':
                    fFB.setUseGPU(!fFB.getUseGPU());
                    this->inval(NULL);
                    return true;
                case 't':
                    fFB.setTriangle(!fFB.getTriangle());
                    this->inval(NULL);
                    return true;
            }
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        fFB.drawBG(canvas);
        if (fFB.getTriangle()) {
            fFB.drawTriangle(canvas, fPts);
        }
        else if (fIsRect) {
            fFB.drawRect(canvas, fPts);
        } else {
            fFB.drawLine(canvas, fPts);
        }
        fFB.drawFG(canvas);

        {
            SkString str;
            str.printf("%s %s %s %s",
                       fFB.getAA() ? "AA" : "BW",
                       FatBits::kHair_Style == fFB.getStyle() ? "Hair" : "Stroke",
                       fFB.getUseGPU() ? "GPU" : "CPU",
                       fFB.getUseClip() ? "clip" : "noclip");
            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setTextSize(16);
            paint.setColor(SK_ColorBLUE);
            canvas->drawText(str.c_str(), str.size(), 10, 16, paint);
        }
    }

    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
                                              unsigned modi) SK_OVERRIDE {
        SkPoint pt = { x, y };
        int index = -1;
        int count = fFB.getTriangle() ? 3 : 2;
        SkScalar tol = 12;

        for (int i = 0; i < count; ++i) {
            if (fPts[i].equalsWithinTolerance(pt, tol)) {
                index = i;
                break;
            }
        }
        return new IndexClick(this, index);
    }

    bool onClick(Click* click) SK_OVERRIDE {
        int index = IndexClick::GetIndex(click);
        if (index >= 0 && index <= 2) {
            fPts[index] = click->fCurr;
        } else {
            SkScalar dx = click->fCurr.fX - click->fPrev.fX;
            SkScalar dy = click->fCurr.fY - click->fPrev.fY;
            fPts[0].offset(dx, dy);
            fPts[1].offset(dx, dy);
            fPts[2].offset(dx, dy);
        }
        this->inval(NULL);
        return true;
    }

private:

    typedef SampleView INHERITED;
};

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

static SkView* MyFactory() { return new DrawLineView; }
static SkViewRegister reg(MyFactory);
