/*
 * 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 "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);
}

static SkShader* createChecker(const SkMatrix& localMatrix) {
//    SkColor colors[] = { 0xFFFDFDFD, 0xFFF4F4F4 };
    SkColor colors[] = { 0xFFFFFFFF, 0xFFFFFFFF };
    SkBitmap bm;
    bm.allocN32Pixels(2, 2);
    bm.lockPixels();
    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(colors[0]);
    *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(colors[1]);
    return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                        SkShader::kRepeat_TileMode, &localMatrix);
}

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(createChecker(fMatrix));

        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:
    virtual 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);
    }

    virtual 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);
