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

#include "modules/skottie/src/effects/Effects.h"

#include "modules/skottie/src/SkottieAdapter.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGColorFilter.h"
#include "src/utils/SkJSON.h"

namespace skottie {
namespace internal {

namespace  {

class HueSaturationEffectAdapter final : public DiscardableAdaptorBase {
public:
    static sk_sp<HueSaturationEffectAdapter> Make(const skjson::ArrayValue& jprops,
                                                  sk_sp<sksg::RenderNode> layer,
                                                  const AnimationBuilder* abuilder) {
        enum : size_t {
            kChannelControl_Index     = 0,
            kChannelRange_Index       = 1,
            kMasterHue_Index          = 2,
            kMasterSat_Index          = 3,
            kMasterLightness_Index    = 4,
            kColorize_Index           = 5,
            kColorizeHue_Index        = 6,
            kColorizeSat_Index        = 7,
            kColorizeLightness_Index  = 8,

            kMax_Index = kColorizeLightness_Index
        };

        auto adapter = sk_sp<HueSaturationEffectAdapter>(
                            new HueSaturationEffectAdapter(std::move(layer)));

        auto* raw_adapter = adapter.get();

        abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops,
                                                                        kChannelControl_Index),
            [raw_adapter](const ScalarValue& c) {
                raw_adapter->fChanCtrl = c;
            });
        abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops,
                                                                        kMasterHue_Index),
            [raw_adapter](const ScalarValue& h) {
                raw_adapter->fMasterHue = h;
            });
        abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops,
                                                                        kMasterSat_Index),
            [raw_adapter](const ScalarValue& s) {
                raw_adapter->fMasterSat = s;
            });
        abuilder->bindProperty<ScalarValue>(EffectBuilder::GetPropValue(jprops,
                                                                        kMasterLightness_Index),
            [raw_adapter](const ScalarValue& l) {
                raw_adapter->fMasterLight = l;
            });

        // TODO: colorize support?

        return adapter;
    }

    const sk_sp<sksg::ExternalColorFilter>& renderNode() const { return fColorFilter; }

protected:
    void onSync() override {
        fColorFilter->setColorFilter(this->makeColorFilter());
    }

private:
    explicit HueSaturationEffectAdapter(sk_sp<sksg::RenderNode> layer)
        : fColorFilter(sksg::ExternalColorFilter::Make(std::move(layer))) {}

    sk_sp<SkColorFilter> makeColorFilter() const {
        enum : uint8_t {
            kMaster_Chan   = 0x01,
            kReds_Chan     = 0x02,
            kYellows_Chan  = 0x03,
            kGreens_Chan   = 0x04,
            kCyans_Chan    = 0x05,
            kBlues_Chan    = 0x06,
            kMagentas_Chan = 0x07,
        };

        // We only support master channel controls at this point.
        if (static_cast<int>(fChanCtrl) != kMaster_Chan) {
            return nullptr;
        }

        // AE semantics:
        //
        // master       hue [degrees]   => color.H offset
        // master       sat [-100..100] => [-100..0) -> [0 .. color.S)
        //                                 ( 0..100] -> (color.S .. 1]
        // master lightness [-100..100] => [-100..0) -> [0 .. color.L]
        //                                 ( 0..100] -> (color.L .. 1]
        const auto h = fMasterHue / 360,
                   s = SkTPin(fMasterSat   / 100, -1.0f, 1.0f),
                   l = SkTPin(fMasterLight / 100, -1.0f, 1.0f),
                   h_bias  = h,
                   s_bias  = std::max(s, 0.0f),
                   s_scale = 1 - std::abs(s),
                   l_bias  = std::max(l, 0.0f),
                   l_scale = 1 - std::abs(l);

        const float hsl_cm[20] = {
            1,       0,       0, 0, h_bias,
            0, s_scale,       0, 0, s_bias,
            0,       0, l_scale, 0, l_bias,
            0,       0,       0, 1,      0,
        };

        return SkColorFilters::HSLAMatrix(hsl_cm);
    }

    const sk_sp<sksg::ExternalColorFilter> fColorFilter;

    float fChanCtrl    = 0.0f,
          fMasterHue   = 0.0f,
          fMasterSat   = 0.0f,
          fMasterLight = 0.0f;

    using INHERITED = DiscardableAdaptorBase;
};

} // namespace

sk_sp<sksg::RenderNode> EffectBuilder::attachHueSaturationEffect(
        const skjson::ArrayValue& jprops, sk_sp<sksg::RenderNode> layer) const {
    return fBuilder->attachDiscardableAdapter<HueSaturationEffectAdapter>(jprops,
                                                                          std::move(layer),
                                                                          fBuilder);
}

} // namespace internal
} // namespace skottie
