/*
 * Copyright 2015 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/SkFont.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkSurface.h"
#include "src/core/SkPaintPriv.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"
#include "tools/timer/Timer.h"
#include "tools/viewer/Slide.h"

#include <array>
#include <stdio.h>

static const int kGrid = 100;
static const int kWidth = 960;
static const int kHeight = 640;

typedef void (*DrawAtlasProc)(SkCanvas*, SkImage*, SkSpan<const SkRSXform>, SkSpan<const SkRect>,
                              SkSpan<const SkColor>, const SkRect*, const SkSamplingOptions&,
                              const SkPaint*);

static void draw_atlas(SkCanvas* canvas, SkImage* atlas, SkSpan<const SkRSXform> xform,
                       SkSpan<const SkRect> tex,
                       SkSpan<const SkColor> colors, const SkRect* cull,
                       const SkSamplingOptions& sampling, const SkPaint* paint) {
    canvas->drawAtlas(atlas, xform, tex, colors, SkBlendMode::kModulate,
                      sampling, cull, paint);
}

static void draw_atlas_sim(SkCanvas* canvas, SkImage* atlas, SkSpan<const SkRSXform> xform,
                           SkSpan<const SkRect> tex,
                           SkSpan<const SkColor> colors, const SkRect* cull,
                           const SkSamplingOptions& sampling, const SkPaint* paint) {
    size_t N = std::min(xform.size(), tex.size());
    if (!colors.empty()) {
        N = std::min(N, colors.size());
    }
    for (size_t i = 0; i < N; ++i) {
        SkMatrix matrix;
        matrix.setRSXform(xform[i]);

        canvas->save();
        canvas->concat(matrix);
        canvas->drawImageRect(atlas, tex[i], tex[i].makeOffset(-tex[i].x(), -tex[i].y()),
                              sampling, paint, SkCanvas::kFast_SrcRectConstraint);
        canvas->restore();
    }
}

class DrawShipSlide : public Slide {
public:
    DrawShipSlide(const char name[], DrawAtlasProc proc) : fProc(proc) {
        fName = name;
    }

protected:
    void load(SkScalar, SkScalar) override {
        fAtlas = ToolUtils::GetResourceAsImage("images/ship.png");
        if (!fAtlas) {
            SkDebugf("\nCould not decode file ship.png. Falling back to penguin mode.\n");
            fAtlas = ToolUtils::GetResourceAsImage("images/baby_tux.png");
            if (!fAtlas) {
                SkDebugf("\nCould not decode file baby_tux.png. Did you forget"
                         " to set the resourcePath?\n");
                return;
            }
        }

        SkScalar anchorX = fAtlas->width()*0.5f;
        SkScalar anchorY = fAtlas->height()*0.5f;
        int currIndex = 0;
        for (int x = 0; x < kGrid; x++) {
            for (int y = 0; y < kGrid; y++) {
                float xPos = (x / (kGrid - 1.0f)) * kWidth;
                float yPos = (y / (kGrid - 1.0f)) * kWidth;

                fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
                                                   SkIntToScalar(fAtlas->width()),
                                                   SkIntToScalar(fAtlas->height()));
                fXform[currIndex] = SkRSXform::MakeFromRadians(0.1f, SK_ScalarPI*0.5f,
                                                               xPos, yPos, anchorX, anchorY);
                currIndex++;
            }
        }
        fTex[currIndex] = SkRect::MakeLTRB(0.0f, 0.0f,
                                           SkIntToScalar(fAtlas->width()),
                                           SkIntToScalar(fAtlas->height()));
        fXform[currIndex] = SkRSXform::MakeFromRadians(0.5f, SK_ScalarPI*0.5f,
                                                       kWidth*0.5f, kHeight*0.5f, anchorX, anchorY);
    }

    void unload() override {
        fAtlas = nullptr;
    }

    void draw(SkCanvas* canvas) override {
        const float kCosDiff = 0.99984769515f;
        const float kSinDiff = 0.01745240643f;

        if (!fAtlas) {
            return;
        }

        SkPaint paint;
        paint.setColor(SK_ColorWHITE);

        SkScalar anchorX = fAtlas->width()*0.5f;
        SkScalar anchorY = fAtlas->height()*0.5f;
        for (int i = 0; i < kGrid*kGrid+1; ++i) {
            SkScalar c = fXform[i].fSCos;
            SkScalar s = fXform[i].fSSin;

            SkScalar dx = c*anchorX - s*anchorY;
            SkScalar dy = s*anchorX + c*anchorY;

            fXform[i].fSCos = kCosDiff*c - kSinDiff*s;
            fXform[i].fSSin = kSinDiff*c + kCosDiff*s;

            dx -= fXform[i].fSCos*anchorX - fXform[i].fSSin*anchorY;
            dy -= fXform[i].fSSin*anchorX + fXform[i].fSCos*anchorY;
            fXform[i].fTx += dx;
            fXform[i].fTy += dy;
        }

        SkSpan<const SkRSXform> xforms = {&fXform[0], kGrid*kGrid+1};
        SkSpan<const SkRect>      texs = {&fTex[0],   kGrid*kGrid+1};
        fProc(canvas, fAtlas.get(), xforms, texs, {}, nullptr,
              SkSamplingOptions(SkFilterMode::kLinear), &paint);
    }

    bool animate(double nanos) override {
        //TODO: use nanos
        //SkScalar angle = SkDoubleToScalar(fmod(1e-9 * nanos * 360 / 24, 360));
        //fAnimatingDrawable->setSweep(angle);
        return true;
    }

private:
    DrawAtlasProc  fProc;

    sk_sp<SkImage> fAtlas;
    std::array<SkRSXform, kGrid*kGrid+1> fXform;
    std::array<SkRect, kGrid*kGrid+1> fTex;
};

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

DEF_SLIDE( return new DrawShipSlide("DrawShip", draw_atlas); )
DEF_SLIDE( return new DrawShipSlide("DrawShipSim", draw_atlas_sim); )
