/*
 * 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 "modules/skottie/include/SkottieProperty.h"

#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/Transform.h"
#include "modules/skottie/src/text/TextAdapter.h"
#include "modules/sksg/include/SkSGOpacityEffect.h"
#include "modules/sksg/include/SkSGPaint.h"

namespace skottie {

bool TextPropertyValue::operator==(const TextPropertyValue& other) const {
    return fTypeface == other.fTypeface
        && fText == other.fText
        && fTextSize == other.fTextSize
        && fStrokeWidth == other.fStrokeWidth
        && fLineHeight == other.fLineHeight
        && fLineShift == other.fLineShift
        && fAscent == other.fAscent
        && fMaxLines == other.fMaxLines
        && fHAlign == other.fHAlign
        && fVAlign == other.fVAlign
        && fResize == other.fResize
        && fLineBreak == other.fLineBreak
        && fDirection == other.fDirection
        && fCapitalization == other.fCapitalization
        && fBox == other.fBox
        && fFillColor == other.fFillColor
        && fStrokeColor == other.fStrokeColor
        && fPaintOrder == other.fPaintOrder
        && fStrokeJoin == other.fStrokeJoin
        && fHasFill == other.fHasFill
        && fHasStroke == other.fHasStroke
        && fDecorator == other.fDecorator
        && fLocale == other.fLocale
        && fFontFamily == other.fFontFamily;
}

bool TextPropertyValue::operator!=(const TextPropertyValue& other) const {
    return !(*this== other);
}

bool TransformPropertyValue::operator==(const TransformPropertyValue& other) const {
    return this->fAnchorPoint == other.fAnchorPoint
        && this->fPosition    == other.fPosition
        && this->fScale       == other.fScale
        && this->fSkew        == other.fSkew
        && this->fSkewAxis    == other.fSkewAxis;
}

bool TransformPropertyValue::operator!=(const TransformPropertyValue& other) const {
    return !(*this == other);
}

// The SK_API attributes are important here due o them being declared as a template.

template <> SK_API
ColorPropertyHandle::PropertyHandle(sk_sp<sksg::Color> node)
    : fNode(std::move(node)), fRevalidator(nullptr) {}

template <> SK_API
ColorPropertyHandle::PropertyHandle(const ColorPropertyHandle& other)
    : fNode(other.fNode), fRevalidator(other.fRevalidator) {}

template <> SK_API
ColorPropertyHandle::~PropertyHandle() {}

template <> SK_API
ColorPropertyValue ColorPropertyHandle::get() const {
    return fNode->getColor();
}

template <> SK_API
void ColorPropertyHandle::set(const ColorPropertyValue& c) {
    fNode->setColor(c);

    if (fRevalidator) {
        fRevalidator->revalidate();
    }
}

template <> SK_API
OpacityPropertyHandle::PropertyHandle(sk_sp<sksg::OpacityEffect> node)
    : fNode(std::move(node)), fRevalidator(nullptr) {}

template <> SK_API
OpacityPropertyHandle::PropertyHandle(const OpacityPropertyHandle& other)
    : fNode(other.fNode), fRevalidator(other.fRevalidator) {}

template <> SK_API
OpacityPropertyHandle::~PropertyHandle() {}

template <> SK_API
OpacityPropertyValue OpacityPropertyHandle::get() const {
    return fNode->getOpacity() * 100;
}

template <> SK_API
void OpacityPropertyHandle::set(const OpacityPropertyValue& o) {
    fNode->setOpacity(o / 100);

    if (fRevalidator) {
        fRevalidator->revalidate();
    }
}

template <> SK_API
TextPropertyHandle::PropertyHandle(sk_sp<internal::TextAdapter> node)
    : fNode(std::move(node)), fRevalidator(nullptr) {}

template <> SK_API
TextPropertyHandle::PropertyHandle(const TextPropertyHandle& other)
    : fNode(other.fNode), fRevalidator(other.fRevalidator) {}

template <> SK_API
TextPropertyHandle::~PropertyHandle() {}

template <> SK_API
TextPropertyValue TextPropertyHandle::get() const {
    return fNode->getText();
}

template<> SK_API
void TextPropertyHandle::set(const TextPropertyValue& t) {
    fNode->setText(t);

    if (fRevalidator) {
        fRevalidator->revalidate();
    }
}

template <> SK_API
TransformPropertyHandle::PropertyHandle(sk_sp<internal::TransformAdapter2D> node)
    : fNode(std::move(node)), fRevalidator(nullptr) {}

template <> SK_API
TransformPropertyHandle::PropertyHandle(const TransformPropertyHandle& other)
    : fNode(other.fNode), fRevalidator(other.fRevalidator) {}

template <> SK_API
TransformPropertyHandle::~PropertyHandle() {}

template <> SK_API
TransformPropertyValue TransformPropertyHandle::get() const {
    return {
        fNode->getAnchorPoint(),
        fNode->getPosition(),
        fNode->getScale(),
        fNode->getRotation(),
        fNode->getSkew(),
        fNode->getSkewAxis()
    };
}

template <> SK_API
void TransformPropertyHandle::set(const TransformPropertyValue& t) {
    fNode->setAnchorPoint(t.fAnchorPoint);
    fNode->setPosition(t.fPosition);
    fNode->setScale(t.fScale);
    fNode->setRotation(t.fRotation);
    fNode->setSkew(t.fSkew);
    fNode->setSkewAxis(t.fSkewAxis);

    if (fRevalidator) {
        fRevalidator->revalidate();
    }
}

void PropertyObserver::onColorProperty(const char[],
                                       const LazyHandle<ColorPropertyHandle>&) {}

void PropertyObserver::onOpacityProperty(const char[],
                                         const LazyHandle<OpacityPropertyHandle>&) {}

void PropertyObserver::onTextProperty(const char[],
                                      const LazyHandle<TextPropertyHandle>&) {}

void PropertyObserver::onTransformProperty(const char[],
                                           const LazyHandle<TransformPropertyHandle>&) {}

void PropertyObserver::onEnterNode(const char node_name[], NodeType) {}

void PropertyObserver::onLeavingNode(const char node_name[], NodeType) {}

}  // namespace skottie
