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

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/effects/SkGradientShader.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "src/core/SkColorFilterPriv.h"
#include "tools/DecodeUtils.h"
#include "tools/GpuToolUtils.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

namespace {

sk_sp<SkShader> create_gradient_shader(SkRect r,
                                       const std::array<SkColor, 3>& colors,
                                       const std::array<float, 3>& offsets) {
    SkPoint pts[2] = { {r.fLeft, r.fTop}, {r.fRight, r.fTop} };

    return SkGradientShader::MakeLinear(pts, colors.data(), offsets.data(), std::size(colors),
                                        SkTileMode::kClamp);
}

sk_sp<SkShader> create_image_shader(SkCanvas* destCanvas, SkTileMode tmX, SkTileMode tmY) {
    SkBitmap bitmap;

    {
        SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
        bitmap.allocPixels(ii);
        bitmap.eraseColor(SK_ColorWHITE);

        SkCanvas tmpCanvas(bitmap);

        SkColor colors[3][3] = {
                { SK_ColorRED,    SK_ColorDKGRAY, SK_ColorBLUE },
                { SK_ColorLTGRAY, SK_ColorCYAN,   SK_ColorYELLOW },
                { SK_ColorGREEN,  SK_ColorWHITE,  SK_ColorMAGENTA }
        };

        for (int y = 0; y < 3; ++y) {
            for (int x = 0; x < 3; ++x) {
                SkPaint paint;
                paint.setColor(colors[y][x]);
                tmpCanvas.drawRect(SkRect::MakeXYWH(x*21, y*21, 22, 22), paint);
            }
        }

        bitmap.setAlphaType(kOpaque_SkAlphaType);
        bitmap.setImmutable();
    }

    sk_sp<SkImage> img = SkImages::RasterFromBitmap(bitmap);
    img = ToolUtils::MakeTextureImage(destCanvas, std::move(img));
    if (img) {
        return img->makeShader(tmX, tmY, SkSamplingOptions());
    } else {
        return nullptr;
    }
}

sk_sp<SkShader> create_blend_shader(SkCanvas* destCanvas, SkBlendMode bm) {
    constexpr SkColor4f kTransYellow = {1.0f, 1.0f, 0.0f, 0.5f};

    sk_sp<SkShader> dst = SkShaders::Color(kTransYellow, nullptr);
    return SkShaders::Blend(bm,
                            std::move(dst),
                            create_image_shader(destCanvas,
                                                SkTileMode::kRepeat, SkTileMode::kRepeat));
}

sk_sp<SkColorFilter> create_grayscale_colorfilter() {
    float matrix[20] = {};
    matrix[0] = matrix[5] = matrix[10] = 0.2126f;
    matrix[1] = matrix[6] = matrix[11] = 0.7152f;
    matrix[2] = matrix[7] = matrix[12] = 0.0722f;
    matrix[18] = 1.0f;
    return SkColorFilters::Matrix(matrix);
}

void draw_image_shader_tile(SkCanvas* canvas, SkRect clipRect) {
    SkPaint p;
    p.setShader(create_image_shader(canvas, SkTileMode::kClamp, SkTileMode::kRepeat));

    SkPath path;
    path.moveTo(1,   1);
    path.lineTo(32,  127);
    path.lineTo(96,  127);
    path.lineTo(127, 1);
    path.lineTo(63,  32);
    path.close();

    canvas->save();
        canvas->clipRect(clipRect);
        canvas->scale(0.5f, 0.5f);
        canvas->drawPath(path, p);

        canvas->save();
            canvas->concat(SkMatrix::RotateDeg(90, {64, 64}));
            canvas->translate(128, 0);
            canvas->drawPath(path, p);
        canvas->restore();
    canvas->restore();
}

void draw_gradient_tile(SkCanvas* canvas, SkRect clipRect) {
    SkRect r{1, 1, 127, 127};
    SkPaint p;
    p.setShader(create_gradient_shader(r,
                                       { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE },
                                       { 0.0f, 0.75f, 1.0f }));

    canvas->save();
        canvas->clipRect(clipRect);
        canvas->translate(128, 0);
        canvas->scale(0.5f, 0.5f);
        canvas->drawRect(r, p);

        canvas->save();
            canvas->concat(SkMatrix::RotateDeg(90, {64, 64}));
            canvas->translate(128, 0);
            canvas->drawRect(r, p);
        canvas->restore();
    canvas->restore();
}

void draw_colorfilter_swatches(SkCanvas* canvas, SkRect clipRect) {
    static constexpr int kNumTilesPerSide = 3;

    SkSize tileSize = { clipRect.width() / kNumTilesPerSide, clipRect.height() / kNumTilesPerSide };

    // Quantize to four colors
    uint8_t table1[256];
    for (int i = 0; i < 256; ++i) {
        table1[i] = (i/64) * 85;
    }

    // table2 is a band-pass filter for 85-170.
    // table3 re-expands that range to 0..255
    uint8_t table2[256], table3[256];
    for (int i = 0; i < 256; ++i) {
        if (i >= 85 && i <= 170) {
            table2[i] = i;
            table3[i] = ((i - 85) / 85.0f) * 255.0f;
        } else {
            table2[i] = 0;
            table3[i] = 0;
        }
    }

    constexpr SkColor SK_ColorGREY = SkColorSetARGB(0xFF, 0x80, 0x80, 0x80);

    sk_sp<SkColorFilter> colorFilters[kNumTilesPerSide*kNumTilesPerSide];
    static const std::array<SkColor, 3> kGradientColors[kNumTilesPerSide*kNumTilesPerSide] = {
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { 0x00000000,    0x80000000,   0xFF000000    },  // the Gaussian CF uses alpha only
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
            { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
    };

    colorFilters[0] = SkColorFilters::Lighting(SK_ColorLTGRAY, 0xFF440000);
    colorFilters[1] = SkColorFilters::Table(table1);
    colorFilters[2] = SkColorFilters::Compose(SkColorFilters::TableARGB(nullptr, table3,
                                                                        table3, table3),
                                              SkColorFilters::TableARGB(nullptr, table2,
                                                                        table2, table2));
    colorFilters[3] = SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kMultiply);
    colorFilters[4] = SkColorFilterPriv::MakeGaussian();

    colorFilters[5] = SkColorFilters::LinearToSRGBGamma();
    colorFilters[6] = SkColorFilters::SRGBToLinearGamma();

    SkPaint p;

    canvas->save();
        canvas->clipRect(clipRect);
        canvas->translate(clipRect.fLeft, clipRect.fTop);

        for (int y = 0; y < kNumTilesPerSide; ++y) {
            for (int x = 0; x < kNumTilesPerSide; ++x) {
                SkRect r = SkRect::MakeXYWH(x * tileSize.width(), y * tileSize.height(),
                                            tileSize.width(), tileSize.height()).makeInset(1.0f,
                                                                                           1.0f);
                int colorFilterIndex = x*kNumTilesPerSide+y;
                p.setShader(create_gradient_shader(r,
                                                   kGradientColors[colorFilterIndex],
                                                   { 0.0f, 0.5f, 1.0f }));
                p.setColorFilter(colorFilters[colorFilterIndex]);
                canvas->drawRect(r, p);
            }
        }

    canvas->restore();
}

void draw_blend_mode_swatches(SkCanvas* canvas, SkRect clipRect) {
    static const int kTileHeight = 16;
    static const int kTileWidth = 16;
    static const SkColor4f kOpaqueWhite { 1.0f, 1.0f, 1.0f, 1.0f };
    static const SkColor4f kTransBluish { 0.0f, 0.5f, 1.0f, 0.5f };
    static const SkColor4f kTransWhite { 1.0f, 1.0f, 1.0f, 0.75f };

    SkPaint dstPaint;
    dstPaint.setColor(kOpaqueWhite);
    dstPaint.setBlendMode(SkBlendMode::kSrc);
    dstPaint.setAntiAlias(false);

    SkPaint srcPaint;
    srcPaint.setColor(kTransBluish);
    srcPaint.setAntiAlias(false);

    SkRect r = SkRect::MakeXYWH(clipRect.fLeft, clipRect.fTop, kTileWidth, kTileHeight);

    // For the first pass we draw: transparent bluish on top of opaque white
    // For the second pass we draw: transparent white on top of transparent bluish
    for (int passes = 0; passes < 2; ++passes) {
        for (int i = 0; i <= (int)SkBlendMode::kLastCoeffMode; ++i) {
            if (r.fLeft+kTileWidth > clipRect.fRight) {
                r.offsetTo(clipRect.fLeft, r.fTop+kTileHeight);
            }

            canvas->drawRect(r.makeInset(1.0f, 1.0f), dstPaint);
            srcPaint.setBlendMode(static_cast<SkBlendMode>(i));
            canvas->drawRect(r.makeInset(2.0f, 2.0f), srcPaint);

            r.offset(kTileWidth, 0.0f);
        }

        r.offsetTo(clipRect.fLeft, r.fTop+kTileHeight);
        srcPaint.setColor(kTransWhite);
        dstPaint.setColor(kTransBluish);
    }
}

} // anonymous namespace

namespace skiagm {

// This is just for bootstrapping Graphite.
class GraphiteStartGM : public GM {
public:
    GraphiteStartGM() = default;

protected:
    static constexpr int kTileWidth = 128;
    static constexpr int kTileHeight = 128;
    static constexpr int kWidth = 3 * kTileWidth;
    static constexpr int kHeight = 3 * kTileHeight;
    static constexpr int kClipInset = 4;

    void onOnceBeforeDraw() override {
        this->setBGColor(SK_ColorBLACK);
        ToolUtils::GetResourceAsBitmap("images/color_wheel.gif", &fBitmap);
    }

    SkString getName() const override { return SkString("graphitestart"); }

    SkISize getISize() override { return SkISize::Make(kWidth, kHeight); }

    void onDraw(SkCanvas* canvas) override {

        const SkRect clipRect = SkRect::MakeWH(kWidth, kHeight).makeInset(kClipInset, kClipInset);

        canvas->save();
        canvas->clipRRect(SkRRect::MakeRectXY(clipRect, 32.f, 32.f), true);

        // Upper-left corner
        draw_image_shader_tile(canvas, SkRect::MakeXYWH(0, 0, kTileWidth, kTileHeight));

        // Upper-middle tile
        draw_gradient_tile(canvas, SkRect::MakeXYWH(kTileWidth, 0, kTileWidth, kTileHeight));

        // Upper-right corner
        draw_colorfilter_swatches(canvas, SkRect::MakeXYWH(2*kTileWidth, 0,
                                                           kTileWidth, kTileWidth));

        // Middle-left tile
        {
            SkPaint p;
            p.setColor(SK_ColorRED);

            SkRect r = SkRect::MakeXYWH(0, kTileHeight, kTileWidth, kTileHeight);
            canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
        }

        // Middle-middle tile
        {
            SkPaint p;
            p.setShader(create_blend_shader(canvas, SkBlendMode::kModulate));

            SkRect r = SkRect::MakeXYWH(kTileWidth, kTileHeight, kTileWidth, kTileHeight);
            canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
        }

        // Middle-right tile
        {
            sk_sp<SkImage> image(ToolUtils::GetResourceAsImage("images/mandrill_128.png"));
            sk_sp<SkShader> shader;

            if (image) {
                shader = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, {});
                shader = shader->makeWithColorFilter(create_grayscale_colorfilter());
            }

            SkPaint p;
            p.setShader(std::move(shader));

            SkRect r = SkRect::MakeXYWH(2*kTileWidth, kTileHeight, kTileWidth, kTileHeight);
            canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
        }

        canvas->restore();

        // Bottom-left corner
#if defined(SK_GRAPHITE)
        // TODO: failing serialize test on Linux, not sure what's going on
        canvas->writePixels(fBitmap, 0, 2*kTileHeight);
#endif

        // Bottom-middle tile
        draw_blend_mode_swatches(canvas, SkRect::MakeXYWH(kTileWidth, 2*kTileHeight,
                                                          kTileWidth, kTileHeight));

        // Bottom-right corner
        {
            const SkRect kTile = SkRect::MakeXYWH(2*kTileWidth, 2*kTileHeight,
                                                  kTileWidth, kTileHeight);

            SkPaint circlePaint;
            circlePaint.setColor(SK_ColorBLUE);
            circlePaint.setBlendMode(SkBlendMode::kSrc);

            canvas->clipRect(kTile);
            canvas->drawRect(kTile.makeInset(10, 20), circlePaint);

            SkPaint restorePaint;
            restorePaint.setBlendMode(SkBlendMode::kPlus);

            canvas->saveLayer(nullptr, &restorePaint);
                circlePaint.setColor(SK_ColorRED);
                circlePaint.setBlendMode(SkBlendMode::kSrc);

                canvas->drawRect(kTile.makeInset(15, 25), circlePaint);
            canvas->restore();
        }
    }

private:
    SkBitmap fBitmap;
};

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

DEF_GM(return new GraphiteStartGM;)

}  // namespace skiagm
