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

#include "gm.h"
#include "SkCanvas.h"
#include "SkVertices.h"
#include "SkPoint.h"

#include <iostream>
#include <vector>

using namespace skiagm;

static const int kCellSize = 60;
static const int kColumnSize = 36;

static const int kBoneCount = 7;
static const SkVertices::Bone kBones[] = {
    {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},   // SkMatrix::I()
    {{ 1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 0.0f }},  // SkMatrix::MakeTrans(10, 0)
    {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 10.0f }},  // SkMatrix::MakeTrans(0, 10)
    {{ 1.0f, 0.0f, 0.0f, 1.0f, -10.0f, 0.0f }}, // SkMatrix::MakeTrans(-10, 0)
    {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -10.0f }}, // SkMatrix::MakeTrans(0, -10)
    {{ 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f }},   // SkMatrix::MakeScale(0.5)
    {{ 1.5f, 0.0f, 0.0f, 1.5f, 0.0f, 0.0f }},   // SkMatrix::MakeScale(1.5)
};

static const int kVertexCount = 4;
static const SkPoint kPositions[] = {
    { 0, 0 },
    { 0, 30 },
    { 30, 30 },
    { 30, 0 },
};
static const SkColor kColors[] = {
    0xFFFF0000,
    0xFF00FF00,
    0xFF0000FF,
    0xFFFFFF00,
};
static const SkVertices::BoneIndices kBoneIndices[] = {
    {{ 1, 0, 0, 0 }},
    {{ 2, 1, 0, 0 }},
    {{ 3, 2, 1, 0 }},
    {{ 4, 3, 2, 1 }},
};
static const SkVertices::BoneWeights kBoneWeights[] = {
    {{ 1.0f,  0.0f,  0.0f,  0.0f  }},
    {{ 0.5f,  0.5f,  0.0f,  0.0f  }},
    {{ 0.34f, 0.33f, 0.33f, 0.0f  }},
    {{ 0.25f, 0.25f, 0.25f, 0.25f }},
};

static const int kIndexCount = 6;
static const uint16_t kIndices[] = {
    0, 1, 2,
    2, 3, 0,
};

// Swap two SkVertices::Bone pointers in place.
static void swap(const SkVertices::Bone** x, const SkVertices::Bone** y) {
    const SkVertices::Bone* temp = *x;
    *x = *y;
    *y = temp;
}

class SkinningGM : public GM {

public:
    SkinningGM(bool deformUsingCPU, bool cache)
            : fPaint()
            , fVertices(nullptr)
            , fDeformUsingCPU(deformUsingCPU)
            , fCache(cache)
    {}

protected:
    bool runAsBench() const override {
        return true;
    }

    SkString onShortName() override {
        SkString name("skinning");
        if (fDeformUsingCPU) {
            name.append("_cpu");
        }
        if (fCache) {
            name.append("_cached");
        }
        return name;
    }

    SkISize onISize() override {
        return SkISize::Make(2400, 2400);
    }

    void onOnceBeforeDraw() override {
        fVertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                         kVertexCount,
                                         kPositions,
                                         nullptr,
                                         kColors,
                                         kBoneIndices,
                                         kBoneWeights,
                                         kIndexCount,
                                         kIndices,
                                         !fCache);
    }

    void onDraw(SkCanvas* canvas) override {
        // Set the initial position.
        int xpos = kCellSize;
        int ypos = kCellSize;

        // Create the mutable set of bones.
        const SkVertices::Bone* bones[kBoneCount];
        for (int i = 0; i < kBoneCount; i ++) {
            bones[i] = &kBones[i];
        }

        // Draw the vertices.
        drawPermutations(canvas, xpos, ypos, bones, 1);
    }

private:
    void drawPermutations(SkCanvas* canvas,
                          int& xpos,
                          int& ypos,
                          const SkVertices::Bone** bones,
                          int start) {
        if (start == kBoneCount) {
            // Reached the end of the permutations, so draw.
            canvas->save();

            // Copy the bones.
            SkVertices::Bone copiedBones[kBoneCount];
            for (int i = 0; i < kBoneCount; i ++) {
                copiedBones[i] = *bones[i];
            }

            // Set the position.
            canvas->translate(xpos, ypos);

            // Draw the vertices.
            if (fDeformUsingCPU) {
                // Apply the bones.
                sk_sp<SkVertices> vertices = fVertices->applyBones(copiedBones,
                                                                   kBoneCount);

                // Deform with CPU.
                canvas->drawVertices(vertices.get(),
                                     SkBlendMode::kSrc,
                                     fPaint);
            } else {
                // Deform with GPU.
                canvas->drawVertices(fVertices.get(),
                                     copiedBones,
                                     kBoneCount,
                                     SkBlendMode::kSrc,
                                     fPaint);
            }

            canvas->restore();

            // Get a new position to draw the vertices.
            xpos += kCellSize;
            if (xpos > kCellSize * kColumnSize) {
                xpos = kCellSize;
                ypos += kCellSize;
            }

            return;
        }

        // Find all possible permutations within the given range.
        for (int i = start; i < kBoneCount; i ++) {
            // Swap the start and i-th elements.
            swap(bones + start, bones + i);

            // Find permutations of the sub array.
            drawPermutations(canvas, xpos, ypos, bones, start + 1);

            // Swap the elements back.
            swap(bones + i, bones + start);
        }
    }

private:
    SkPaint fPaint;
    sk_sp<SkVertices> fVertices;
    bool fDeformUsingCPU;
    bool fCache;

    typedef GM INHERITED;
};

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

DEF_GM(return new SkinningGM(true, true);)
DEF_GM(return new SkinningGM(false, true);)
DEF_GM(return new SkinningGM(true, false);)
DEF_GM(return new SkinningGM(false, false);)
