/*
 * 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 "Nima.h"

#include "SkString.h"
#include "SkVertices.h"
#include "SkPaint.h"
#include "Resources.h"
#include <algorithm>

#include <iostream>

using namespace nima;

SampleActor::SampleActor(std::string baseName)
    : fTexture(nullptr)
    , fActorImages()
    , fPaint(nullptr) {
    // Load the NIMA data.
    SkString nimaSkPath = GetResourcePath(("nima/" + baseName + ".nima").c_str());
    std::string nimaPath(nimaSkPath.c_str());
    INHERITED::load(nimaPath);

    // Load the image asset.
    fTexture = GetResourceAsImage(("nima/" + baseName + ".png").c_str());

    // Create the paint.
    fPaint = std::make_unique<SkPaint>();
    fPaint->setShader(fTexture->makeShader(nullptr));

    // Load the image nodes.
    fActorImages.reserve(m_ImageNodeCount);
    for (uint32_t i = 0; i < m_ImageNodeCount; i ++) {
        fActorImages.emplace_back(m_ImageNodes[i], fTexture, fPaint.get());
    }

    // Sort the image nodes.
    std::sort(fActorImages.begin(), fActorImages.end(), [](auto a, auto b) {
        return a.drawOrder() < b.drawOrder();
    });
}

SampleActor::~SampleActor() {
}

void SampleActor::render(SkCanvas* canvas) const {
    // Render the image nodes.
    for (auto image : fActorImages) {
        image.render(this, canvas);
    }
}

SampleActorImage::SampleActorImage(ActorImage* actorImage, sk_sp<SkImage> texture, SkPaint* paint)
    : fActorImage(actorImage)
    , fTexture(texture)
    , fPaint(paint) {
}

SampleActorImage::~SampleActorImage() {
}

void SampleActorImage::render(const SampleActor* actor, SkCanvas* canvas) const {
    // Retrieve data from the image.
    uint32_t  vertexCount  = fActorImage->vertexCount();
    uint32_t  vertexStride = fActorImage->vertexStride();
    float*    vertexData   = fActorImage->vertices();
    uint32_t  indexCount   = fActorImage->triangleCount() * 3;
    uint16_t* indexData    = fActorImage->triangles();

    // Don't render if not visible.
    if (!vertexCount || fActorImage->textureIndex() < 0) {
        return;
    }

    // Split the vertex data.
    std::vector<SkPoint>  positions(vertexCount);
    std::vector<SkPoint>  texs(vertexCount);
    for (uint32_t i = 0; i < vertexCount; i ++) {
        uint32_t j = i * vertexStride;

        // Get the attributes.
        float* attrPosition = vertexData + j;
        float* attrTex      = vertexData + j + 2;
        float* attrBoneIdx  = vertexData + j + 4;
        float* attrBoneWgt  = vertexData + j + 8;

        // Deform the position.
        Vec2D position(attrPosition[0], attrPosition[1]);
        if (fActorImage->connectedBoneCount() > 0) {
            position = deform(position, attrBoneIdx, attrBoneWgt);
        } else {
            position = deform(position, nullptr, nullptr);
        }

        // Set the data.
        positions[i].set(position[0], position[1]);
        texs[i].set(attrTex[0] * fTexture->width(), attrTex[1] * fTexture->height());
    }

    // Create vertices.
    sk_sp<SkVertices> vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
                                                      vertexCount,
                                                      positions.data(),
                                                      texs.data(),
                                                      nullptr,
                                                      indexCount,
                                                      indexData);

    // Determine the blend mode.
    SkBlendMode blendMode;
    switch (fActorImage->blendMode()) {
        case BlendMode::Off: {
            blendMode = SkBlendMode::kSrc;
            break;
        }
        case BlendMode::Normal: {
            blendMode = SkBlendMode::kSrcOver;
            break;
        }
        case BlendMode::Additive: {
            blendMode = SkBlendMode::kPlus;
            break;
        }
        case BlendMode::Multiply: {
            blendMode = SkBlendMode::kMultiply;
            break;
        }
        case BlendMode::Screen: {
            blendMode = SkBlendMode::kScreen;
            break;
        }
    }

    // Set the opacity.
    fPaint->setAlpha(static_cast<U8CPU>(fActorImage->renderOpacity() * 255));

    // Draw the vertices.
    canvas->drawVertices(vertices, blendMode, *fPaint);

    // Reset the opacity.
    fPaint->setAlpha(255);
}

Vec2D SampleActorImage::deform(const Vec2D& position, float* boneIdx, float* boneWgt) const {
    float px = position[0], py = position[1];
    float px2 = px, py2 = py;
    float influence[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };

    // Apply the world transform.
    Mat2D worldTransform = fActorImage->worldTransform();
    px2 = worldTransform[0] * px + worldTransform[2] * py + worldTransform[4];
    py2 = worldTransform[1] * px + worldTransform[3] * py + worldTransform[5];

    // Apply deformations based on bone offsets.
    if (boneIdx && boneWgt) {
        float* matrices = fActorImage->boneInfluenceMatrices();

        for (uint32_t i = 0; i < 4; i ++) {
            int index = static_cast<int>(boneIdx[i]);
            float weight = boneWgt[i];
            for (int j = 0; j < 6; j ++) {
                influence[j] += matrices[index * 6 + j] * weight;
            }
        }

        px = influence[0] * px2 + influence[2] * py2 + influence[4];
        py = influence[1] * px2 + influence[3] * py2 + influence[5];
    } else {
        px = px2;
        py = py2;
    }

    // Return the transformed position.
    return Vec2D(px, py);
}
