#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/artboard.hpp"
#include "rive/layout_component.hpp"
#include "rive/node.hpp"
#include "rive/math/aabb.hpp"
#ifdef WITH_RIVE_LAYOUT
#include "rive/transform_component.hpp"
#include "yoga/YGEnums.h"
#include "yoga/YGFloatOptional.h"
#endif
#include <vector>

using namespace rive;

void LayoutComponent::buildDependencies()
{
    Super::buildDependencies();
    if (parent() != nullptr)
    {
        parent()->addDependent(this);
    }
}

#ifdef WITH_RIVE_LAYOUT
LayoutComponent::LayoutComponent() : m_layoutData(std::unique_ptr<LayoutData>(new LayoutData()))
{
    layoutNode().getConfig()->setPointScaleFactor(0);
}

StatusCode LayoutComponent::onAddedDirty(CoreContext* context)
{
    auto code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }

    auto coreStyle = context->resolve(styleId());
    if (coreStyle == nullptr || !coreStyle->is<LayoutComponentStyle>())
    {
        return StatusCode::MissingObject;
    }
    m_style = static_cast<LayoutComponentStyle*>(coreStyle);
    addChild(m_style);
    artboard()->markLayoutDirty(this);
    markLayoutStyleDirty();
    if (parent() != nullptr && parent()->is<LayoutComponent>())
    {
        parent()->as<LayoutComponent>()->syncLayoutChildren();
    }
    return StatusCode::Ok;
}

void LayoutComponent::update(ComponentDirt value)
{
    if (hasDirt(value, ComponentDirt::WorldTransform))
    {
        Mat2D parentWorld = parent()->is<WorldTransformComponent>()
                                ? (parent()->as<WorldTransformComponent>())->worldTransform()
                                : Mat2D();
        auto transform = Mat2D();
        transform[4] = m_layoutLocationX;
        transform[5] = m_layoutLocationY;

        auto multipliedTransform = Mat2D::multiply(parentWorld, transform);
        m_WorldTransform = multipliedTransform;
    }
}

static YGSize measureFunc(YGNode* node,
                          float width,
                          YGMeasureMode widthMode,
                          float height,
                          YGMeasureMode heightMode)
{
    Vec2D size = ((LayoutComponent*)node->getContext())
                     ->measureLayout(width,
                                     (LayoutMeasureMode)widthMode,
                                     height,
                                     (LayoutMeasureMode)heightMode);

    return YGSize{size.x, size.y};
}

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode heightMode)
{
    Vec2D size = Vec2D();
    for (auto child : children())
    {
        if (child->is<LayoutComponent>())
        {
            continue;
        }
        if (child->is<TransformComponent>())
        {
            auto transformComponent = child->as<TransformComponent>();
            Vec2D measured =
                transformComponent->measureLayout(width, widthMode, height, heightMode);
            size = Vec2D(std::max(size.x, measured.x), std::max(size.y, measured.y));
        }
    }
    return size;
}

void LayoutComponent::syncStyle()
{
    if (m_style == nullptr)
    {
        return;
    }
    YGNode& ygNode = layoutNode();
    YGStyle& ygStyle = layoutStyle();
    if (m_style->intrinsicallySized())
    {
        ygNode.setContext(this);
        ygNode.setMeasureFunc(measureFunc);
    }
    else
    {
        ygNode.setMeasureFunc(nullptr);
    }
    if (m_style->widthUnits() != YGUnitAuto)
    {
        ygStyle.dimensions()[YGDimensionWidth] = YGValue{width(), m_style->widthUnits()};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionWidth] = YGValueAuto;
    }
    if (m_style->heightUnits() != YGUnitAuto)
    {
        ygStyle.dimensions()[YGDimensionHeight] = YGValue{height(), m_style->heightUnits()};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionHeight] = YGValueAuto;
    }
    ygStyle.minDimensions()[YGDimensionWidth] =
        YGValue{m_style->minWidth(), m_style->minWidthUnits()};
    ygStyle.minDimensions()[YGDimensionHeight] =
        YGValue{m_style->minHeight(), m_style->minHeightUnits()};
    ygStyle.maxDimensions()[YGDimensionWidth] =
        YGValue{m_style->maxWidth(), m_style->maxWidthUnits()};
    ygStyle.maxDimensions()[YGDimensionHeight] =
        YGValue{m_style->maxHeight(), m_style->maxHeightUnits()};

    ygStyle.gap()[YGGutterColumn] =
        YGValue{m_style->gapHorizontal(), m_style->gapHorizontalUnits()};
    ygStyle.gap()[YGGutterRow] = YGValue{m_style->gapVertical(), m_style->gapVerticalUnits()};
    ygStyle.border()[YGEdgeLeft] = YGValue{m_style->borderLeft(), m_style->borderLeftUnits()};
    ygStyle.border()[YGEdgeRight] = YGValue{m_style->borderRight(), m_style->borderRightUnits()};
    ygStyle.border()[YGEdgeTop] = YGValue{m_style->borderTop(), m_style->borderTopUnits()};
    ygStyle.border()[YGEdgeBottom] = YGValue{m_style->borderBottom(), m_style->borderBottomUnits()};
    ygStyle.margin()[YGEdgeLeft] = YGValue{m_style->marginLeft(), m_style->marginLeftUnits()};
    ygStyle.margin()[YGEdgeRight] = YGValue{m_style->marginRight(), m_style->marginRightUnits()};
    ygStyle.margin()[YGEdgeTop] = YGValue{m_style->marginTop(), m_style->marginTopUnits()};
    ygStyle.margin()[YGEdgeBottom] = YGValue{m_style->marginBottom(), m_style->marginBottomUnits()};
    ygStyle.padding()[YGEdgeLeft] = YGValue{m_style->paddingLeft(), m_style->paddingLeftUnits()};
    ygStyle.padding()[YGEdgeRight] = YGValue{m_style->paddingRight(), m_style->paddingRightUnits()};
    ygStyle.padding()[YGEdgeTop] = YGValue{m_style->paddingTop(), m_style->paddingTopUnits()};
    ygStyle.padding()[YGEdgeBottom] =
        YGValue{m_style->paddingBottom(), m_style->paddingBottomUnits()};
    ygStyle.position()[YGEdgeLeft] = YGValue{m_style->positionLeft(), m_style->positionLeftUnits()};
    ygStyle.position()[YGEdgeRight] =
        YGValue{m_style->positionRight(), m_style->positionRightUnits()};
    ygStyle.position()[YGEdgeTop] = YGValue{m_style->positionTop(), m_style->positionTopUnits()};
    ygStyle.position()[YGEdgeBottom] =
        YGValue{m_style->positionBottom(), m_style->positionBottomUnits()};

    ygStyle.display() = m_style->display();
    ygStyle.positionType() = m_style->positionType();
    ygStyle.flex() = YGFloatOptional(m_style->flex());
    ygStyle.flexGrow() = YGFloatOptional(m_style->flexGrow());
    ygStyle.flexShrink() = YGFloatOptional(m_style->flexShrink());
    // ygStyle.flexBasis() = m_style->flexBasis();
    ygStyle.flexDirection() = m_style->flexDirection();
    ygStyle.flexWrap() = m_style->flexWrap();
    ygStyle.alignItems() = m_style->alignItems();
    ygStyle.alignContent() = m_style->alignContent();
    ygStyle.alignSelf() = m_style->alignSelf();
    ygStyle.justifyContent() = m_style->justifyContent();

    ygNode.setStyle(ygStyle);
}

void LayoutComponent::syncLayoutChildren()
{
    YGNodeRemoveAllChildren(&layoutNode());
    int index = 0;
    for (size_t i = 0; i < children().size(); i++)
    {
        Component* child = children()[i];
        if (child->is<LayoutComponent>())
        {
            YGNodeInsertChild(&layoutNode(), &child->as<LayoutComponent>()->layoutNode(), index);
            index += 1;
        }
    }
}

void LayoutComponent::propagateSize()
{
    if (artboard() == this)
    {
        return;
    }
    propagateSizeToChildren(this);
}

void LayoutComponent::propagateSizeToChildren(ContainerComponent* component)
{
    for (auto child : component->children())
    {
        if (child->is<LayoutComponent>() || child->coreType() == NodeBase::typeKey)
        {
            continue;
        }
        if (child->is<TransformComponent>())
        {
            auto sizableChild = child->as<TransformComponent>();
            sizableChild->controlSize(Vec2D(m_layoutSizeWidth, m_layoutSizeHeight));
        }
        if (child->is<ContainerComponent>())
        {
            propagateSizeToChildren(child->as<ContainerComponent>());
        }
    }
}

void LayoutComponent::calculateLayout()
{
    YGNodeCalculateLayout(&layoutNode(), width(), height(), YGDirection::YGDirectionInherit);
}

void LayoutComponent::updateLayoutBounds()
{
    auto node = &layoutNode();
    auto left = YGNodeLayoutGetLeft(node);
    auto top = YGNodeLayoutGetTop(node);
    auto width = YGNodeLayoutGetWidth(node);
    auto height = YGNodeLayoutGetHeight(node);
    if (animates())
    {
        auto toBounds = m_animationData.toBounds;
        if (left != toBounds.left() || top != toBounds.top() || width != toBounds.width() ||
            height != toBounds.height())
        {
            m_animationData.elapsedSeconds = 0;
            m_animationData.fromBounds = AABB(m_layoutLocationX,
                                              m_layoutLocationY,
                                              m_layoutLocationX + this->width(),
                                              m_layoutLocationY + this->height());
            m_animationData.toBounds = AABB(left, top, left + width, top + height);
            propagateSize();
            markWorldTransformDirty();
        }
    }
    else if (left != m_layoutLocationX || top != m_layoutLocationY || width != m_layoutSizeWidth ||
             height != m_layoutSizeHeight)
    {
        m_layoutLocationX = left;
        m_layoutLocationY = top;
        m_layoutSizeWidth = width;
        m_layoutSizeHeight = height;
        propagateSize();
        markWorldTransformDirty();
    }
}

bool LayoutComponent::advance(double elapsedSeconds) { return applyInterpolation(elapsedSeconds); }

bool LayoutComponent::animates()
{
    if (m_style == nullptr)
    {
        return false;
    }
    return m_style->positionType() == YGPositionType::YGPositionTypeRelative &&
           m_style->animationStyle() != LayoutAnimationStyle::none &&
           interpolation() != LayoutStyleInterpolation::hold && interpolationTime() > 0;
}

LayoutAnimationStyle LayoutComponent::animationStyle()
{
    if (m_style == nullptr)
    {
        return LayoutAnimationStyle::none;
    }
    return m_style->animationStyle();
}

KeyFrameInterpolator* LayoutComponent::interpolator()
{
    if (m_style == nullptr)
    {
        return nullptr;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
            return m_inheritedInterpolator != nullptr ? m_inheritedInterpolator
                                                      : m_style->interpolator();
        case LayoutAnimationStyle::custom:
            return m_style->interpolator();
        default:
            return nullptr;
    }
}

LayoutStyleInterpolation LayoutComponent::interpolation()
{
    auto defaultInterpolation = LayoutStyleInterpolation::hold;
    if (m_style == nullptr)
    {
        return defaultInterpolation;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
            return m_inheritedInterpolation;
        case LayoutAnimationStyle::custom:
            return m_style->interpolation();
        default:
            return defaultInterpolation;
    }
}

float LayoutComponent::interpolationTime()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    switch (m_style->animationStyle())
    {
        case LayoutAnimationStyle::inherit:
            return m_inheritedInterpolationTime;
        case LayoutAnimationStyle::custom:
            return m_style->interpolationTime();
        default:
            return 0;
    }
}

void LayoutComponent::cascadeAnimationStyle(LayoutStyleInterpolation inheritedInterpolation,
                                            KeyFrameInterpolator* inheritedInterpolator,
                                            float inheritedInterpolationTime)
{
    if (m_style != nullptr && m_style->animationStyle() == LayoutAnimationStyle::inherit)
    {
        setInheritedInterpolation(inheritedInterpolation,
                                  inheritedInterpolator,
                                  inheritedInterpolationTime);
    }
    else
    {
        clearInheritedInterpolation();
    }
    for (auto child : children())
    {
        if (child->is<LayoutComponent>())
        {
            child->as<LayoutComponent>()->cascadeAnimationStyle(interpolation(),
                                                                interpolator(),
                                                                interpolationTime());
        }
    }
}

void LayoutComponent::setInheritedInterpolation(LayoutStyleInterpolation inheritedInterpolation,
                                                KeyFrameInterpolator* inheritedInterpolator,
                                                float inheritedInterpolationTime)
{
    m_inheritedInterpolation = inheritedInterpolation;
    m_inheritedInterpolator = inheritedInterpolator;
    m_inheritedInterpolationTime = inheritedInterpolationTime;
}

void LayoutComponent::clearInheritedInterpolation()
{
    m_inheritedInterpolation = LayoutStyleInterpolation::hold;
    m_inheritedInterpolator = nullptr;
    m_inheritedInterpolationTime = 0;
}

bool LayoutComponent::applyInterpolation(double elapsedSeconds)
{
    if (!animates() || m_style == nullptr || m_animationData.toBounds == layoutBounds())
    {
        return false;
    }
    if (m_animationData.elapsedSeconds >= interpolationTime())
    {
        m_layoutLocationX = m_animationData.toBounds.left();
        m_layoutLocationY = m_animationData.toBounds.top();
        m_layoutSizeWidth = m_animationData.toBounds.width();
        m_layoutSizeHeight = m_animationData.toBounds.height();
        m_animationData.elapsedSeconds = 0;
        markWorldTransformDirty();
        return false;
    }
    float f = 1;
    if (interpolationTime() > 0)
    {
        f = m_animationData.elapsedSeconds / interpolationTime();
    }
    bool needsAdvance = false;
    auto fromBounds = m_animationData.fromBounds;
    auto toBounds = m_animationData.toBounds;
    auto left = m_layoutLocationX;
    auto top = m_layoutLocationY;
    auto width = m_layoutSizeWidth;
    auto height = m_layoutSizeHeight;
    if (toBounds.left() != left || toBounds.top() != top)
    {
        if (interpolation() == LayoutStyleInterpolation::linear)
        {
            left = fromBounds.left() + f * (toBounds.left() - fromBounds.left());
            top = fromBounds.top() + f * (toBounds.top() - fromBounds.top());
        }
        else
        {
            if (interpolator() != nullptr)
            {
                left = interpolator()->transformValue(fromBounds.left(), toBounds.left(), f);
                top = interpolator()->transformValue(fromBounds.top(), toBounds.top(), f);
            }
        }
        needsAdvance = true;
        m_layoutLocationX = left;
        m_layoutLocationY = top;
    }
    if (toBounds.width() != width || toBounds.height() != height)
    {
        if (interpolation() == LayoutStyleInterpolation::linear)
        {
            width = fromBounds.width() + f * (toBounds.width() - fromBounds.width());
            height = fromBounds.height() + f * (toBounds.height() - fromBounds.height());
        }
        else
        {
            if (interpolator() != nullptr)
            {
                width = interpolator()->transformValue(fromBounds.width(), toBounds.width(), f);
                height = interpolator()->transformValue(fromBounds.height(), toBounds.height(), f);
            }
        }
        needsAdvance = true;
        m_layoutSizeWidth = width;
        m_layoutSizeHeight = height;
    }
    m_animationData.elapsedSeconds = m_animationData.elapsedSeconds + (float)elapsedSeconds;
    if (needsAdvance)
    {
        propagateSize();
        markWorldTransformDirty();
        markLayoutNodeDirty();
    }
    return needsAdvance;
}

void LayoutComponent::markLayoutNodeDirty()
{
    layoutNode().markDirtyAndPropagate();
    artboard()->markLayoutDirty(this);
}

void LayoutComponent::markLayoutStyleDirty()
{
    clearInheritedInterpolation();
    addDirt(ComponentDirt::LayoutStyle);
    if (artboard() != this)
    {
        artboard()->markLayoutStyleDirty();
    }
}
#else
void LayoutComponent::markLayoutNodeDirty() {}
void LayoutComponent::markLayoutStyleDirty() {}
#endif

void LayoutComponent::clipChanged() { markLayoutNodeDirty(); }
void LayoutComponent::widthChanged() { markLayoutNodeDirty(); }
void LayoutComponent::heightChanged() { markLayoutNodeDirty(); }
void LayoutComponent::styleIdChanged() { markLayoutNodeDirty(); }