/*
 * 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 "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTileMode.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkAssert.h"
#include "include/private/SkTPin.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/effects/Effects.h"
#include "modules/sksg/include/SkSGNode.h"
#include "modules/sksg/include/SkSGRenderNode.h"

#include <array>
#include <cmath>
#include <cstdio>
#include <utility>
#include <vector>

namespace skjson {
class ArrayValue;
}
namespace sksg {
class InvalidationController;
}

namespace skottie::internal {
namespace {

// This shader maps its child shader onto a sphere.  To simplify things, we set it up such that:
//
//   - the sphere is centered at origin and has r == 1
//   - the eye is positioned at (0,0,eye_z), where eye_z is chosen to visually match AE
//   - the POI for a given pixel is on the z = 0 plane (x,y,0)
//   - we're only rendering inside the projected circle, which guarantees a quadratic solution
//
// Effect stages:
//
//   1) ray-cast to find the sphere intersection (selectable front/back solution);
//      given the sphere geometry, this is also the normal
//   2) rotate the normal
//   3) UV-map the sphere
//   4) scale uv to source size and sample
//   5) apply lighting model
//
// Note: the current implementation uses two passes for two-side ("full") rendering, on the
//       assumption that in practice most textures are opaque and two-side mode is infrequent;
//       if this proves to be problematic, we could expand the implementation to blend both sides
//       in one pass.
//
static constexpr char gSphereSkSL[] =
    "uniform shader child;"

    "uniform half3x3 rot_matrix;"
    "uniform half2 child_scale;"
    "uniform half side_select;"

    // apply_light()
    "%s"

    "half3 to_sphere(half3 EYE) {"
        "half eye_z2 = EYE.z*EYE.z;"

        "half a = dot(EYE, EYE),"
             "b = -2*eye_z2,"
             "c = eye_z2 - 1,"
             "t = (-b + side_select*sqrt(b*b - 4*a*c))/(2*a);"

        "return half3(0, 0, -EYE.z) + EYE*t;"
    "}"

    "half4 main(float2 xy) {"
        "half3 EYE = half3(xy, -5.5),"
                "N = to_sphere(EYE),"
               "RN = rot_matrix*N;"

        "half kRPI = 1/3.1415927;"

        "half2 UV = half2("
            "0.5 + kRPI * 0.5 * atan(RN.x, RN.z),"
            "0.5 + kRPI * asin(RN.y)"
        ");"

        "return apply_light(EYE, N, child.eval(UV*child_scale));"
    "}"
;

// CC Sphere uses a Phong-like lighting model:
//
//   - "ambient" controls the intensity of the texture color
//   - "diffuse" controls a multiplicative mix of texture and light color
//   - "specular" controls a light color specular component
//   - "roughness" is the specular exponent reciprocal
//   - "light intensity" modulates the diffuse and specular components (but not ambient)
//   - "light height" and "light direction" specify the light source position in spherical coords
//
// Implementation-wise, light intensity/height/direction are all combined into l_vec.
// For efficiency, we fall back to a stripped-down shader (ambient-only) when the diffuse & specular
// components are not used.
//
// TODO: "metal" and "reflective" parameters are ignored.
static constexpr char gBasicLightSkSL[] =
    "uniform half l_coeff_ambient;"

    "half4 apply_light(half3 EYE, half3 N, half4 c) {"
        "c.rgb *= l_coeff_ambient;"
        "return c;"
    "}"
;

static constexpr char gFancyLightSkSL[] =
    "uniform half3 l_vec;"
    "uniform half3 l_color;"
    "uniform half l_coeff_ambient;"
    "uniform half l_coeff_diffuse;"
    "uniform half l_coeff_specular;"
    "uniform half l_specular_exp;"

    "half4 apply_light(half3 EYE, half3 N, half4 c) {"
        "half3 LR = reflect(-l_vec*side_select, N);"
        "half s_base = max(dot(normalize(EYE), LR), 0),"

        "a = l_coeff_ambient,"
        "d = l_coeff_diffuse * max(dot(l_vec, N), 0),"
        "s = l_coeff_specular * saturate(pow(s_base, l_specular_exp));"

        "c.rgb = (a + d*l_color)*c.rgb + s*l_color*c.a;"

        "return c;"
    "}"
;

static sk_sp<SkRuntimeEffect> sphere_fancylight_effect() {
    static const SkRuntimeEffect* effect =
            SkRuntimeEffect::MakeForShader(SkStringPrintf(gSphereSkSL, gFancyLightSkSL), {})
                    .effect.release();
    if (0 && !effect) {
        printf("!!! %s\n",
               SkRuntimeEffect::MakeForShader(SkStringPrintf(gSphereSkSL, gFancyLightSkSL), {})
                       .errorText.c_str());
    }
    SkASSERT(effect);

    return sk_ref_sp(effect);
}

static sk_sp<SkRuntimeEffect> sphere_basiclight_effect() {
    static const SkRuntimeEffect* effect =
            SkRuntimeEffect::MakeForShader(SkStringPrintf(gSphereSkSL, gBasicLightSkSL), {})
                    .effect.release();
    SkASSERT(effect);

    return sk_ref_sp(effect);
}

class SphereNode final : public sksg::CustomRenderNode {
public:
    SphereNode(sk_sp<RenderNode> child, const SkSize& child_size)
        : INHERITED({std::move(child)})
        , fChildSize(child_size) {}

    enum class RenderSide {
        kFull,
        kOutside,
        kInside,
    };

    SG_ATTRIBUTE(Center  , SkPoint   , fCenter)
    SG_ATTRIBUTE(Radius  , float     , fRadius)
    SG_ATTRIBUTE(Rotation, SkM44     , fRot   )
    SG_ATTRIBUTE(Side    , RenderSide, fSide  )

    SG_ATTRIBUTE(LightVec     , SkV3 , fLightVec     )
    SG_ATTRIBUTE(LightColor   , SkV3 , fLightColor   )
    SG_ATTRIBUTE(AmbientLight , float, fAmbientLight )
    SG_ATTRIBUTE(DiffuseLight , float, fDiffuseLight )
    SG_ATTRIBUTE(SpecularLight, float, fSpecularLight)
    SG_ATTRIBUTE(SpecularExp  , float, fSpecularExp  )

private:
    sk_sp<SkShader> contentShader() {
        if (!fContentShader || this->hasChildrenInval()) {
            const auto& child = this->children()[0];
            child->revalidate(nullptr, SkMatrix::I());

            SkPictureRecorder recorder;
            child->render(recorder.beginRecording(SkRect::MakeSize(fChildSize)));

            fContentShader = recorder.finishRecordingAsPicture()
                    ->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkFilterMode::kLinear,
                                 nullptr, nullptr);
        }

        return fContentShader;
    }

    sk_sp<SkShader> buildEffectShader(float selector) {
        const auto has_fancy_light =
                fLightVec.length() > 0 && (fDiffuseLight > 0 || fSpecularLight > 0);

        SkRuntimeShaderBuilder builder(has_fancy_light
                                           ? sphere_fancylight_effect()
                                           : sphere_basiclight_effect());

        builder.child  ("child")       = this->contentShader();
        builder.uniform("child_scale") = fChildSize;
        builder.uniform("side_select") = selector;
        builder.uniform("rot_matrix")  = std::array<float,9>{
            fRot.rc(0,0), fRot.rc(0,1), fRot.rc(0,2),
            fRot.rc(1,0), fRot.rc(1,1), fRot.rc(1,2),
            fRot.rc(2,0), fRot.rc(2,1), fRot.rc(2,2),
        };

        builder.uniform("l_coeff_ambient")  = fAmbientLight;

        if (has_fancy_light) {
            builder.uniform("l_vec")            = fLightVec * -selector;
            builder.uniform("l_color")          = fLightColor;
            builder.uniform("l_coeff_diffuse")  = fDiffuseLight;
            builder.uniform("l_coeff_specular") = fSpecularLight;
            builder.uniform("l_specular_exp")   = fSpecularExp;
        }

        const auto lm = SkMatrix::Translate(fCenter.fX, fCenter.fY) *
                        SkMatrix::Scale(fRadius, fRadius);

        return builder.makeShader(&lm);
    }

    SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
        fSphereShader.reset();
        if (fSide != RenderSide::kOutside) {
            fSphereShader = this->buildEffectShader(1);
        }
        if (fSide != RenderSide::kInside) {
            auto outside = this->buildEffectShader(-1);
            fSphereShader = fSphereShader
                    ? SkShaders::Blend(SkBlendMode::kSrcOver,
                                       std::move(fSphereShader),
                                       std::move(outside))
                    : std::move(outside);
        }
        SkASSERT(fSphereShader);

        return SkRect::MakeLTRB(fCenter.fX - fRadius,
                                fCenter.fY - fRadius,
                                fCenter.fX + fRadius,
                                fCenter.fY + fRadius);
    }

    void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
        if (fRadius <= 0) {
            return;
        }

        SkPaint sphere_paint;
        sphere_paint.setAntiAlias(true);
        sphere_paint.setShader(fSphereShader);

        canvas->drawCircle(fCenter, fRadius, sphere_paint);
    }

    const RenderNode* onNodeAt(const SkPoint&) const override { return nullptr; } // no hit-testing

    const SkSize fChildSize;

    // Cached shaders
    sk_sp<SkShader> fSphereShader;
    sk_sp<SkShader> fContentShader;

    // Effect controls.
    SkM44      fRot;
    SkPoint    fCenter = {0,0};
    float      fRadius = 0;
    RenderSide fSide   = RenderSide::kFull;

    SkV3       fLightVec      = {0,0,1},
               fLightColor    = {1,1,1};
    float      fAmbientLight  = 1,
               fDiffuseLight  = 0,
               fSpecularLight = 0,
               fSpecularExp   = 0;

    using INHERITED = sksg::CustomRenderNode;
};

class SphereAdapter final : public DiscardableAdapterBase<SphereAdapter, SphereNode> {
public:
    SphereAdapter(const skjson::ArrayValue& jprops,
                  const AnimationBuilder* abuilder,
                  sk_sp<SphereNode> node)
        : INHERITED(std::move(node))
    {
        enum : size_t {
            //      kRotGrp_Index =  0,
                      kRotX_Index =  1,
                      kRotY_Index =  2,
                      kRotZ_Index =  3,
                  kRotOrder_Index =  4,
            // ???                =  5,
                    kRadius_Index =  6,
                    kOffset_Index =  7,
                    kRender_Index =  8,

            //       kLight_Index =  9,
            kLightIntensity_Index = 10,
                kLightColor_Index = 11,
               kLightHeight_Index = 12,
            kLightDirection_Index = 13,
            // ???                = 14,
            //     kShading_Index = 15,
                   kAmbient_Index = 16,
                   kDiffuse_Index = 17,
                  kSpecular_Index = 18,
                 kRoughness_Index = 19,
        };

        EffectBinder(jprops, *abuilder, this)
            .bind(  kOffset_Index, fOffset  )
            .bind(  kRadius_Index, fRadius  )
            .bind(    kRotX_Index, fRotX    )
            .bind(    kRotY_Index, fRotY    )
            .bind(    kRotZ_Index, fRotZ    )
            .bind(kRotOrder_Index, fRotOrder)
            .bind(  kRender_Index, fRender  )

            .bind(kLightIntensity_Index, fLightIntensity)
            .bind(    kLightColor_Index, fLightColor    )
            .bind(   kLightHeight_Index, fLightHeight   )
            .bind(kLightDirection_Index, fLightDirection)
            .bind(       kAmbient_Index, fAmbient       )
            .bind(       kDiffuse_Index, fDiffuse       )
            .bind(      kSpecular_Index, fSpecular      )
            .bind(     kRoughness_Index, fRoughness     );
    }

private:
    void onSync() override {
        const auto side = [](ScalarValue s) {
            switch (SkScalarRoundToInt(s)) {
                case 1:  return SphereNode::RenderSide::kFull;
                case 2:  return SphereNode::RenderSide::kOutside;
                case 3:
                default: return SphereNode::RenderSide::kInside;
            }
            SkUNREACHABLE;
        };

        const auto rotation = [](ScalarValue order,
                                 ScalarValue x, ScalarValue y, ScalarValue z) {
            const SkM44 rx = SkM44::Rotate({1,0,0}, SkDegreesToRadians( x)),
                        ry = SkM44::Rotate({0,1,0}, SkDegreesToRadians( y)),
                        rz = SkM44::Rotate({0,0,1}, SkDegreesToRadians(-z));

            switch (SkScalarRoundToInt(order)) {
                case 1: return rx * ry * rz;
                case 2: return rx * rz * ry;
                case 3: return ry * rx * rz;
                case 4: return ry * rz * rx;
                case 5: return rz * rx * ry;
                case 6:
               default: return rz * ry * rx;
            }
            SkUNREACHABLE;
        };

        const auto light_vec = [](float height, float direction) {
            float z = std::sin(height * SK_ScalarPI / 2),
                  r = std::sqrt(1 - z*z),
                  x = std::cos(direction) * r,
                  y = std::sin(direction) * r;

            return SkV3{x,y,z};
        };

        const auto& sph = this->node();

        sph->setCenter({fOffset.x, fOffset.y});
        sph->setRadius(fRadius);
        sph->setSide(side(fRender));
        sph->setRotation(rotation(fRotOrder, fRotX, fRotY, fRotZ));

        sph->setAmbientLight (SkTPin(fAmbient * 0.01f, 0.0f, 2.0f));

        const auto intensity = SkTPin(fLightIntensity * 0.01f,  0.0f, 10.0f);
        sph->setDiffuseLight (SkTPin(fDiffuse * 0.01f, 0.0f, 1.0f) * intensity);
        sph->setSpecularLight(SkTPin(fSpecular* 0.01f, 0.0f, 1.0f) * intensity);

        sph->setLightVec(light_vec(
            SkTPin(fLightHeight    * 0.01f, -1.0f,  1.0f),
            SkDegreesToRadians(fLightDirection - 90)
        ));

        const auto lc = static_cast<SkColor4f>(fLightColor);
        sph->setLightColor({lc.fR, lc.fG, lc.fB});

        sph->setSpecularExp(1/SkTPin(fRoughness, 0.001f, 0.5f));
    }

    Vec2Value   fOffset   = {0,0};
    ScalarValue fRadius   = 0,
                fRotX     = 0,
                fRotY     = 0,
                fRotZ     = 0,
                fRotOrder = 1,
                fRender   = 1;

    ColorValue  fLightColor;
    ScalarValue fLightIntensity =   0,
                fLightHeight    =   0,
                fLightDirection =   0,
                fAmbient        = 100,
                fDiffuse        =   0,
                fSpecular       =   0,
                fRoughness      =   0.5f;

    using INHERITED = DiscardableAdapterBase<SphereAdapter, SphereNode>;
};

} // namespace

sk_sp<sksg::RenderNode> EffectBuilder::attachSphereEffect(
        const skjson::ArrayValue& jprops, sk_sp<sksg::RenderNode> layer) const {
    auto sphere = sk_make_sp<SphereNode>(std::move(layer), fLayerSize);

    return fBuilder->attachDiscardableAdapter<SphereAdapter>(jprops, fBuilder, std::move(sphere));
}

} // namespace skottie::internal
