/*
 * 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 SkMatrix kBones[] = {
    SkMatrix::I(),
    SkMatrix::MakeTrans(10, 0),
    SkMatrix::MakeTrans(0, 10),
    SkMatrix::MakeTrans(-10, 0),
    SkMatrix::MakeTrans(0, -10),
    SkMatrix::MakeScale(0.5f),
    SkMatrix::MakeScale(1.5f),
};

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 SkMatrix pointers in place.
static void swap(const SkMatrix** x, const SkMatrix** y) {
    const SkMatrix* temp = *x;
    *x = *y;
    *y = temp;
}

class SkinningGM : public GM {

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

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

    SkString onShortName() override {
        SkString name("skinning");
        if (fDeformUsingCPU) {
            name.append("_cpu");
        }
        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,
                                         false); // Keep the vertices non-volatile.
    }

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

        // Create the mutable set of bones.
        const SkMatrix* 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 SkMatrix** bones,
                          int start) {
        if (start == kBoneCount) {
            // Reached the end of the permutations, so draw.
            canvas->save();

            // Copy the bones.
            SkMatrix 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) {
                // Deform with CPU.
                std::vector<SkPoint> positions(kVertexCount);
                for (int i = 0; i < kVertexCount; i ++) {
                    const SkVertices::BoneIndices& indices = kBoneIndices[i];
                    const SkVertices::BoneWeights& weights = kBoneWeights[i];

                    // Apply deformations.
                    SkPoint& result = positions[i];
                    SkPoint transformed;
                    for (uint32_t j = 0; j < 4; j ++) {
                        // Get the bone attachment data.
                        uint32_t index = indices.indices[j];
                        float weight = weights.weights[j];

                        // Skip the bone is there is no weight.
                        if (weight == 0.0f) {
                            continue;
                        }
                        SkASSERT(index != 0);

                        // transformed = M * v
                        copiedBones[index].mapPoints(&transformed, &kPositions[i], 1);

                        // result += transformed * w
                        result += transformed * weight;
                    }
                }

                sk_sp<SkVertices> vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                                                  kVertexCount,
                                                                  positions.data(),
                                                                  nullptr,
                                                                  kColors,
                                                                  kIndexCount,
                                                                  kIndices);
                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;

    typedef GM INHERITED;
};

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

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