#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/artboard.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/constraints/layout_constraint.hpp"
#include "rive/drawable.hpp"
#include "rive/factory.hpp"
#include "rive/intrinsically_sizeable.hpp"
#include "rive/layout_component.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/node.hpp"
#include "rive/math/aabb.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/shapes/rectangle.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/layout/layout_data.hpp"
#include "rive/layout/layout_component_style.hpp"
#ifdef WITH_RIVE_LAYOUT
#include "rive/transform_component.hpp"
#include "yoga/YGEnums.h"
#include "yoga/YGFloatOptional.h"
#endif
#include <vector>

using namespace rive;

#if defined(WITH_RIVE_LAYOUT) && defined(WITH_RIVE_TOOLS) && defined(DEBUG)
uint32_t LayoutData::count = 0;
#endif

void LayoutComponent::buildDependencies()
{
    Super::buildDependencies();
    if (parent() != nullptr)
    {
        parent()->addDependent(this);
    }
    // Set the blend mode on all the shape paints. If we ever animate this
    // property, we'll need to update it in the update cycle/mark dirty when the
    // blend mode changes.
    for (auto paint : m_ShapePaints)
    {
        paint->blendMode(blendMode());
    }
}

Core* LayoutComponent::hitTest(HitInfo*, const Mat2D&) { return nullptr; }

bool LayoutComponent::hitTestPoint(const Vec2D& position,
                                   bool skipOnUnclipped,
                                   bool isPrimaryHit)
{
    Mat2D inverseWorld;
    if (worldTransform().invert(&inverseWorld))
    {
        // If the layout is not clipped and skipOnUnclipped is true, we
        // don't care about whether it contains the position
        auto canSkip = skipOnUnclipped && !this->clip();
        if (!canSkip)
        {
            auto localWorld = inverseWorld * position;
            if (this->is<Artboard>())
            {
                auto artboard = this->as<Artboard>();
                if (artboard->originX() != 0 || artboard->originY() != 0)
                {
                    localWorld +=
                        Vec2D(artboard->originX() * artboard->layoutWidth(),
                              artboard->originY() * artboard->layoutHeight());
                }
            }
            if (!localBounds().contains(localWorld))
            {
                return false;
            }
        }
        return Drawable::hitTestPoint(position, true, isPrimaryHit);
    }
    return false;
}

void LayoutComponent::update(ComponentDirt value)
{
    Super::update(value);
#ifdef WITH_RIVE_LAYOUT
    if (value == ComponentDirt::Filthy)
    {
        // Use this to prevent layout animation on startup
        interruptAnimation();
    }
#endif
    if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        propagateOpacity(childOpacity());
    }
    if (parent() != nullptr && hasDirt(value, ComponentDirt::WorldTransform))
    {
        Mat2D parentWorld =
            parent()->is<WorldTransformComponent>()
                ? (parent()->as<WorldTransformComponent>())->worldTransform()
                : Mat2D();
        auto location = Vec2D(m_layout.left(), m_layout.top());
        if (parent()->is<Artboard>())
        {
            auto art = parent()->as<Artboard>();
            location -= Vec2D(art->layoutWidth() * art->originX(),
                              art->layoutHeight() * art->originY());
        }
        auto transform = Mat2D::fromTranslation(location);
        m_WorldTransform = Mat2D::multiply(parentWorld, transform);
        updateConstraints();
    }
    if (hasDirt(value,
                ComponentDirt::Path | ComponentDirt::WorldTransform |
                    ComponentDirt::LayoutStyle))
    {
        updateRenderPath();
    }
}

void LayoutComponent::widthOverride(float width, int unitValue, bool isRow)
{
    m_widthOverride = width;
    m_widthUnitValueOverride = unitValue;
    m_parentIsRow = isRow;
    markLayoutNodeDirty();
}

void LayoutComponent::heightOverride(float height, int unitValue, bool isRow)
{
    m_heightOverride = height;
    m_heightUnitValueOverride = unitValue;
    m_parentIsRow = isRow;
    markLayoutNodeDirty();
}

void LayoutComponent::parentIsRow(bool isRow)
{
    m_parentIsRow = isRow;
    markLayoutNodeDirty();
}

void LayoutComponent::widthIntrinsicallySizeOverride(bool intrinsic)
{
    m_widthIntrinsicallySizeOverride = intrinsic;
    // If we have an intrinsically sized override, set units to auto
    // otherwise set to points
    m_widthUnitValueOverride = intrinsic ? 3 : 1;
    markLayoutNodeDirty();
}

void LayoutComponent::heightIntrinsicallySizeOverride(bool intrinsic)
{
    m_heightIntrinsicallySizeOverride = intrinsic;
    // If we have an intrinsically sized override, set units to auto
    // otherwise set to points
    m_heightUnitValueOverride = intrinsic ? 3 : 1;
    markLayoutNodeDirty();
}

void LayoutComponent::forcedWidth(float width)
{
    if (m_forcedWidth == width)
    {
        return;
    }
    m_forcedWidth = width;
    markLayoutStyleDirty();
    markLayoutNodeDirty();
}

void LayoutComponent::forcedHeight(float height)
{
    if (m_forcedHeight == height)
    {
        return;
    }
    m_forcedHeight = height;
    markLayoutStyleDirty();
    markLayoutNodeDirty();
}

void LayoutComponent::updateConstraints()
{
    if (m_layoutConstraints.size() > 0)
    {
        for (auto parentConstraint : m_layoutConstraints)
        {
            parentConstraint->constrainChild(this);
        }
    }
    Super::updateConstraints();
}

bool LayoutComponent::overridesKeyedInterpolation(int propertyKey)
{
#ifdef WITH_RIVE_LAYOUT
    if (animates())
    {
        switch (propertyKey)
        {
            case LayoutComponentBase::widthPropertyKey:
            case LayoutComponentBase::heightPropertyKey:
                return true;
            default:
                return false;
        }
    }
#endif
    return false;
}

bool LayoutComponent::isHidden() const
{
    return Super::isHidden() || isCollapsed();
}

bool LayoutComponent::isCollapsed() const
{
    if (Super::isCollapsed())
    {
        return true;
    }
#ifdef WITH_RIVE_LAYOUT
    return styleDisplayHidden();
#endif
    return false;
}

void LayoutComponent::propagateCollapse(bool collapse)
{
    for (Component* child : children())
    {
        child->collapse(collapse || isCollapsed());
    }
}

bool LayoutComponent::collapse(bool value)
{
    if (!Component::collapse(value))
    {
        return false;
    }
    for (Component* child : children())
    {
        child->collapse(value || isCollapsed());
    }
    return true;
}

#ifdef WITH_RIVE_LAYOUT

LayoutComponent::LayoutComponent() :
    m_layoutData(new LayoutData()), m_proxy(this)
{
    m_layoutData->node.getConfig()->setPointScaleFactor(0);
}

float LayoutComponent::gapHorizontal()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    return m_style->gapHorizontalUnits() == YGUnitPercent
               ? (m_style->gapHorizontal() / 100.0f) * layoutWidth()
               : m_style->gapHorizontal();
}

float LayoutComponent::gapVertical()
{
    if (m_style == nullptr)
    {
        return 0;
    }
    return m_style->gapVerticalUnits() == YGUnitPercent
               ? (m_style->gapVertical() / 100.0f) * layoutHeight()
               : m_style->gapVertical();
}

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);

    return StatusCode::Ok;
}

StatusCode LayoutComponent::onAddedClean(CoreContext* context)
{
    auto code = Super::onAddedClean(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
    markLayoutStyleDirty();
    m_backgroundRect.originX(0);
    m_backgroundRect.originY(0);
    syncLayoutChildren();
    propagateCollapse(isCollapsed());
    return StatusCode::Ok;
}

void LayoutComponent::drawProxy(Renderer* renderer)
{
    if (clip())
    {
        renderer->save();
        renderer->clipPath(m_worldPath.renderPath(this));
    }
    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->shouldDraw())
        {
            continue;
        }
        auto shapePaintPath = shapePaint->pickPath(this);
        if (shapePaintPath == nullptr)
        {
            continue;
        }
        shapePaint->draw(renderer, shapePaintPath, worldTransform());
    }
}

void LayoutComponent::draw(Renderer* renderer)
{
    // Restore clip before drawing stroke so we don't clip the stroke
    if (clip())
    {
        renderer->restore();
    }
}

void LayoutComponent::updateRenderPath()
{
    if (isHidden())
    {
        return;
    }
    m_backgroundRect.width(m_layout.width());
    m_backgroundRect.height(m_layout.height());
    if (style() != nullptr)
    {
        bool isLTR = actualDirection() != LayoutDirection::rtl;
        auto linkedValue = style()->cornerRadiusTL();
        auto tl = isLTR ? style()->cornerRadiusTL() : style()->cornerRadiusTR();
        auto tr = isLTR ? style()->cornerRadiusTR() : style()->cornerRadiusTL();
        auto bl = isLTR ? style()->cornerRadiusBL() : style()->cornerRadiusBR();
        auto br = isLTR ? style()->cornerRadiusBR() : style()->cornerRadiusBL();
        m_backgroundRect.linkCornerRadius(style()->linkCornerRadius());
        m_backgroundRect.cornerRadiusTL(
            style()->linkCornerRadius() ? linkedValue : tl);
        m_backgroundRect.cornerRadiusTR(
            style()->linkCornerRadius() ? linkedValue : tr);
        m_backgroundRect.cornerRadiusBL(
            style()->linkCornerRadius() ? linkedValue : bl);
        m_backgroundRect.cornerRadiusBR(
            style()->linkCornerRadius() ? linkedValue : br);
    }
    m_backgroundRect.update(ComponentDirt::Path);

    m_localPath.rewind();
    m_localPath.addPath(m_backgroundRect.rawPath());

    m_worldPath.rewind(false, FillRule::clockwise);
    m_worldPath.addPath(m_backgroundRect.rawPath(), &m_WorldTransform);

    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->shouldDraw())
        {
            continue;
        }
        if (shapePaint->is<Stroke>())
        {
            shapePaint->as<Stroke>()->invalidateEffects();
        }
    }
}

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;
        }
        auto sizeableChild = IntrinsicallySizeable::from(child);
        if (sizeableChild != nullptr)
        {
            Vec2D measured = sizeableChild->measureLayout(width,
                                                          widthMode,
                                                          height,
                                                          heightMode);
            size = Vec2D(std::max(size.x, measured.x),
                         std::max(size.y, measured.y));
        }
    }
    return size;
}

bool LayoutComponent::mainAxisIsRow()
{
    if (style() == nullptr)
    {
        return true;
    }
    return style()->flexDirection() == YGFlexDirectionRow ||
           style()->flexDirection() == YGFlexDirectionRowReverse;
}

bool LayoutComponent::mainAxisIsColumn()
{
    if (style() == nullptr)
    {
        return false;
    }
    return style()->flexDirection() == YGFlexDirectionColumn ||
           style()->flexDirection() == YGFlexDirectionColumnReverse;
}

bool LayoutComponent::isLeaf()
{
    for (auto child : children())
    {
        auto layout = LayoutNodeProvider::from(child);
        if (layout != nullptr)
        {
            return false;
        }
    }
    return true;
}

void* LayoutComponent::layoutNode(int index)
{
    if (m_layoutData != nullptr)
    {
        return static_cast<void*>(&m_layoutData->node);
    }
    return nullptr;
}

void LayoutComponent::syncStyle()
{
    if (m_style == nullptr || m_layoutData == nullptr)
    {
        return;
    }
    YGNode& ygNode = m_layoutData->node;
    YGStyle& ygStyle = m_layoutData->style;
    if (m_style->intrinsicallySized() && isLeaf())
    {
        ygNode.setContext(this);
        ygNode.setMeasureFunc(measureFunc);
    }
    else
    {
        ygNode.setMeasureFunc(nullptr);
    }

    auto realWidth = width();
    auto realWidthUnits = m_style->widthUnits();
    auto realWidthScaleType = m_style->widthScaleType();
    auto realHeight = height();
    auto realHeightUnits = m_style->heightUnits();
    auto realHeightScaleType = m_style->heightScaleType();
    auto parentIsRow =
        layoutParent() != nullptr ? layoutParent()->mainAxisIsRow() : true;

    // If we have override width/height values, use those.
    // Currently we only use these for Artboards that are part of a
    // NestedArtboardLayout but perhaps there will be other use cases for
    // overriding in the future?
    if (canHaveOverrides())
    {
        if (!std::isnan(m_widthOverride))
        {
            realWidth = m_widthOverride;
        }
        if (!std::isnan(m_heightOverride))
        {
            realHeight = m_heightOverride;
        }
        parentIsRow = m_parentIsRow;

        if (m_widthUnitValueOverride != -1)
        {
            realWidthUnits = YGUnit(m_widthUnitValueOverride);
            switch (realWidthUnits)
            {
                case YGUnitPoint:
                case YGUnitPercent:
                    realWidthScaleType = LayoutScaleType::fixed;
                    break;
                case YGUnitAuto:
                    if (m_widthIntrinsicallySizeOverride)
                    {
                        realWidthScaleType = LayoutScaleType::hug;
                    }
                    else
                    {
                        realWidthScaleType = LayoutScaleType::fill;
                    }
                    break;
                default:
                    break;
            }
        }
        if (m_heightUnitValueOverride != -1)
        {
            realHeightUnits = YGUnit(m_heightUnitValueOverride);
            switch (realHeightUnits)
            {
                case YGUnitPoint:
                case YGUnitPercent:
                    realHeightScaleType = LayoutScaleType::fixed;
                    break;
                case YGUnitAuto:
                    if (m_heightIntrinsicallySizeOverride)
                    {
                        realHeightScaleType = LayoutScaleType::hug;
                    }
                    else
                    {
                        realHeightScaleType = LayoutScaleType::fill;
                    }
                    break;
                default:
                    break;
            }
        }
    }
    if (!std::isnan(m_forcedWidth))
    {
        ygStyle.dimensions()[YGDimensionWidth] =
            YGValue{std::max(0.0f, m_forcedWidth), YGUnitPoint};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionWidth] =
            YGValue{std::max(0.0f, realWidth), realWidthUnits};
    }
    if (!std::isnan(m_forcedHeight))
    {
        ygStyle.dimensions()[YGDimensionHeight] =
            YGValue{std::max(0.0f, m_forcedHeight), YGUnitPoint};
    }
    else
    {
        ygStyle.dimensions()[YGDimensionHeight] =
            YGValue{std::max(0.0f, realHeight), realHeightUnits};
    }

    switch (realWidthScaleType)
    {
        case LayoutScaleType::fixed:
            if (parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(0);
                ygStyle.flexShrink() = YGFloatOptional(0);
                ygStyle.flexBasis() = YGValue{m_style->flexBasis(), YGUnitAuto};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignAuto;
            }
            break;
        case LayoutScaleType::fill:
            if (parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(fractionalWidth());
                ygStyle.flexShrink() = YGFloatOptional(fractionalWidth());
                ygStyle.flexBasis() =
                    YGValue{m_style->flexBasis(), m_style->flexBasisUnits()};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignStretch;
            }
            break;
        case LayoutScaleType::hug:
            if (parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(0);
                ygStyle.flexShrink() = YGFloatOptional(0);
                ygStyle.flexBasis() = YGValue{m_style->flexBasis(), YGUnitAuto};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignAuto;
            }
            break;
        default:
            break;
    }

    switch (realHeightScaleType)
    {
        case LayoutScaleType::fixed:
            if (!parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(0);
                ygStyle.flexShrink() = YGFloatOptional(0);
                ygStyle.flexBasis() = YGValue{m_style->flexBasis(), YGUnitAuto};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignAuto;
            }
            break;
        case LayoutScaleType::fill:
            if (!parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(fractionalHeight());
                ygStyle.flexShrink() = YGFloatOptional(fractionalHeight());
                ygStyle.flexBasis() =
                    YGValue{m_style->flexBasis(), m_style->flexBasisUnits()};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignStretch;
            }
            break;
        case LayoutScaleType::hug:
            if (!parentIsRow)
            {
                ygStyle.flexGrow() = YGFloatOptional(0);
                ygStyle.flexShrink() = YGFloatOptional(0);
                ygStyle.flexBasis() = YGValue{m_style->flexBasis(), YGUnitAuto};
            }
            else
            {
                ygStyle.alignSelf() = YGAlignAuto;
            }
            break;
        default:
            break;
    }

    bool isRowForAlignment = mainAxisIsRow();
    switch (m_style->alignmentType())
    {
        case LayoutAlignmentType::topLeft:
        case LayoutAlignmentType::topCenter:
        case LayoutAlignmentType::topRight:
            if (isRowForAlignment)
            {
                ygStyle.alignItems() = YGAlignFlexStart;
                ygStyle.alignContent() = YGAlignFlexStart;
            }
            else
            {
                ygStyle.justifyContent() = YGJustifyFlexStart;
            }
            break;
        case LayoutAlignmentType::centerLeft:
        case LayoutAlignmentType::center:
        case LayoutAlignmentType::centerRight:
            if (isRowForAlignment)
            {
                ygStyle.alignItems() = YGAlignCenter;
                ygStyle.alignContent() = YGAlignCenter;
            }
            else
            {
                ygStyle.justifyContent() = YGJustifyCenter;
            }
            break;
        case LayoutAlignmentType::bottomLeft:
        case LayoutAlignmentType::bottomCenter:
        case LayoutAlignmentType::bottomRight:
            if (isRowForAlignment)
            {
                ygStyle.alignItems() = YGAlignFlexEnd;
                ygStyle.alignContent() = YGAlignFlexEnd;
            }
            else
            {
                ygStyle.justifyContent() = YGJustifyFlexEnd;
            }
            break;
        default:
            break;
    }
    switch (m_style->alignmentType())
    {
        case LayoutAlignmentType::topLeft:
        case LayoutAlignmentType::centerLeft:
        case LayoutAlignmentType::bottomLeft:
            if (isRowForAlignment)
            {
                ygStyle.justifyContent() = YGJustifyFlexStart;
            }
            else
            {
                ygStyle.alignItems() = YGAlignFlexStart;
                ygStyle.alignContent() = YGAlignFlexStart;
            }
            break;
        case LayoutAlignmentType::topCenter:
        case LayoutAlignmentType::center:
        case LayoutAlignmentType::bottomCenter:
            if (isRowForAlignment)
            {
                ygStyle.justifyContent() = YGJustifyCenter;
            }
            else
            {
                ygStyle.alignItems() = YGAlignCenter;
                ygStyle.alignContent() = YGAlignCenter;
            }
            break;
        case LayoutAlignmentType::topRight:
        case LayoutAlignmentType::centerRight:
        case LayoutAlignmentType::bottomRight:
            if (isRowForAlignment)
            {
                ygStyle.justifyContent() = YGJustifyFlexEnd;
            }
            else
            {
                ygStyle.alignItems() = YGAlignFlexEnd;
                ygStyle.alignContent() = YGAlignFlexEnd;
            }
            break;
        case LayoutAlignmentType::spaceBetweenStart:
            ygStyle.alignItems() = YGAlignFlexStart;
            ygStyle.alignContent() = YGAlignFlexStart;
            ygStyle.justifyContent() = YGJustifySpaceBetween;
            break;
        case LayoutAlignmentType::spaceBetweenCenter:
            ygStyle.alignItems() = YGAlignCenter;
            ygStyle.alignContent() = YGAlignCenter;
            ygStyle.justifyContent() = YGJustifySpaceBetween;
            break;
        case LayoutAlignmentType::spaceBetweenEnd:
            ygStyle.alignItems() = YGAlignFlexEnd;
            ygStyle.alignContent() = YGAlignFlexEnd;
            ygStyle.justifyContent() = YGJustifySpaceBetween;
            break;
    }

    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()};

    bool isLTR = actualDirection() != LayoutDirection::rtl;
    auto startEdge = isLTR ? YGEdgeLeft : YGEdgeRight;
    auto endEdge = isLTR ? YGEdgeRight : YGEdgeLeft;
    ygStyle.border()[startEdge] =
        YGValue{m_style->borderLeft(), m_style->borderLeftUnits()};
    ygStyle.border()[endEdge] =
        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()};

    bool hasLayoutParent = layoutParent() != nullptr;
    ygStyle.margin()[startEdge] =
        YGValue{m_style->marginLeft(),
                hasLayoutParent ? m_style->marginLeftUnits() : YGUnitPoint};
    ygStyle.margin()[endEdge] =
        YGValue{m_style->marginRight(),
                hasLayoutParent ? m_style->marginRightUnits() : YGUnitPoint};
    ygStyle.margin()[YGEdgeTop] =
        YGValue{m_style->marginTop(),
                hasLayoutParent ? m_style->marginTopUnits() : YGUnitPoint};
    ygStyle.margin()[YGEdgeBottom] =
        YGValue{m_style->marginBottom(),
                hasLayoutParent ? m_style->marginBottomUnits() : YGUnitPoint};

    ygStyle.padding()[startEdge] =
        YGValue{m_style->paddingLeft(), m_style->paddingLeftUnits()};
    ygStyle.padding()[endEdge] =
        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()[startEdge] =
        YGValue{m_style->positionLeft(), m_style->positionLeftUnits()};
    ygStyle.position()[endEdge] =
        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.flexDirection() = m_style->flexDirection();
    ygStyle.flexWrap() = m_style->flexWrap();
    ygStyle.direction() = m_style->direction();

    ygNode.setStyle(ygStyle);
}

void LayoutComponent::clearLayoutChildren()
{
    YGNode& ourNode = m_layoutData->node;
    YGNodeRemoveAllChildren(&ourNode);
}

void LayoutComponent::syncLayoutChildren()
{
    YGNode& ourNode = m_layoutData->node;
    YGNodeRemoveAllChildren(&ourNode);
    int index = 0;
    for (auto child : children())
    {
        YGNode* node = nullptr;
        switch (child->coreType())
        {
            case LayoutComponentBase::typeKey:
                node = &child->as<LayoutComponent>()->m_layoutData->node;
                if (node != nullptr)
                {
                    ourNode.insertChild(node, index++);
                    node->setOwner(&ourNode);
                    ourNode.markDirtyAndPropagate();
                }
                break;
            case NestedArtboardLayoutBase::typeKey:
                node = static_cast<YGNode*>(
                    child->as<NestedArtboardLayout>()->layoutNode(0));
                if (node != nullptr)
                {
                    ourNode.insertChild(node, index++);
                    node->setOwner(&ourNode);
                    ourNode.markDirtyAndPropagate();
                }
                break;
            case ArtboardComponentListBase::typeKey:
                auto list = child->as<ArtboardComponentList>();
                for (int i = 0; i < list->artboardCount(); i++)
                {
                    node = static_cast<YGNode*>(list->layoutNode(i));
                    if (node != nullptr)
                    {
                        ourNode.insertChild(node, index++);
                        node->setOwner(&ourNode);
                        ourNode.markDirtyAndPropagate();
                    }
                }
                break;
        }
    }
    markLayoutNodeDirty();
}

void LayoutComponent::propagateSize() { propagateSizeToChildren(this); }

void LayoutComponent::propagateSizeToChildren(ContainerComponent* component)
{
    if (isHidden())
    {
        return;
    }
    for (auto child : component->children())
    {
        if (child->is<LayoutComponent>() ||
            child->coreType() == NodeBase::typeKey)
        {
            continue;
        }
        auto sizeableChild = IntrinsicallySizeable::from(child);
        if (sizeableChild != nullptr && m_style != nullptr)
        {
            LayoutScaleType widthScaleType = m_style->widthScaleType();
            LayoutScaleType heightScaleType = m_style->heightScaleType();
            sizeableChild->controlSize(
                Vec2D(m_layout.width(), m_layout.height()),
                widthScaleType,
                heightScaleType,
                actualDirection());

            if (!sizeableChild->shouldPropagateSizeToChildren())
            {
                // Do not propagate to its children
                continue;
            }
        }
        if (child->is<ContainerComponent>())
        {
            propagateSizeToChildren(child->as<ContainerComponent>());
        }
    }
}

void LayoutComponent::calculateLayoutInternal(float availableWidth,
                                              float availableHeight)
{
    auto actualAvailWidth =
        std::isnan(availableWidth) && m_style && m_style->intrinsicallySized()
            ? availableWidth
            : width();
    auto actualAvailHeight =
        std::isnan(availableHeight) && m_style && m_style->intrinsicallySized()
            ? availableHeight
            : height();
    YGNodeCalculateLayout(&m_layoutData->node,
                          actualAvailWidth,
                          actualAvailHeight,
                          YGDirection::YGDirectionInherit);
}

bool LayoutComponent::styleDisplayHidden() const
{
    if (m_style == nullptr)
    {
        return false;
    }
    return m_style->display() == YGDisplayNone;
}

LayoutDirection LayoutComponent::actualDirection()
{
    if (m_style == nullptr)
    {
        return m_inheritedDirection;
    }
    switch (m_style->direction())
    {
        case YGDirectionLTR:
            return LayoutDirection::ltr;
        case YGDirectionRTL:
            return LayoutDirection::rtl;
        default:
            return m_inheritedDirection;
    }
}

void LayoutComponent::onDirty(ComponentDirt value)
{
    Super::onDirty(value);
    if ((value & ComponentDirt::WorldTransform) ==
            ComponentDirt::WorldTransform &&
        clip())
    {
        addDirt(ComponentDirt::Path);
    }
}

static Layout layoutFromYoga(const YGLayout& layout)
{
    return Layout(layout.position[YGEdgeLeft],
                  layout.position[YGEdgeTop],
                  layout.dimensions[YGDimensionWidth],
                  layout.dimensions[YGDimensionHeight]);
}

static LayoutPadding layoutPaddingFromYoga(const YGLayout& layout)
{
    return LayoutPadding(layout.padding[YGEdgeLeft],
                         layout.padding[YGEdgeTop],
                         layout.padding[YGEdgeRight],
                         layout.padding[YGEdgeBottom]);
}

void LayoutComponent::updateLayoutBounds(bool animate)
{
    YGNode& node = m_layoutData->node;
    bool updated = node.getHasNewLayout();
    if (!updated)
    {
        return;
    }
    node.setHasNewLayout(false);

    for (auto child : children())
    {
        auto layout = LayoutNodeProvider::from(child);
        if (layout != nullptr)
        {
            layout->updateLayoutBounds(animate);
        }
    }

    auto yogaLayout = node.getLayout();
    Layout newLayout = layoutFromYoga(yogaLayout);
    m_layoutPadding = layoutPaddingFromYoga(yogaLayout);

    if (animate && animates())
    {
        auto animationData = currentAnimationData();
        if (newLayout != animationData->to || m_forceUpdateLayoutBounds)
        {
            if (animationData->elapsedSeconds != 0.0f)
            {
                if (m_isSmoothingAnimation)
                {
                    // we were already smoothening.
                    m_animationDataA.copy(m_animationDataB);
                }
                m_isSmoothingAnimation = true;
            }
            else
            {
                m_isSmoothingAnimation = false;
            }
            animationData = currentAnimationData();
            animationData->from = m_layout;
            animationData->to = newLayout;
            animationData->elapsedSeconds = 0.0f;
            propagateSize();
            markWorldTransformDirty();
        }
    }
    else if (newLayout != m_layout || m_forceUpdateLayoutBounds)
    {
        if (m_layout.width() != newLayout.width() ||
            m_layout.height() != newLayout.height())
        {
            // Width changed, we need to rebuild the path.
            addDirt(ComponentDirt::Path);
        }
        m_animationDataA.to = m_layout = newLayout;

        propagateSize();
        markWorldTransformDirty();
    }
    m_forceUpdateLayoutBounds = false;
}

bool LayoutComponent::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    return applyInterpolation(elapsedSeconds,
                              (flags & AdvanceFlags::Animate) ==
                                      AdvanceFlags::Animate ||
                                  (flags & AdvanceFlags::AdvanceNested) ==
                                      AdvanceFlags::AdvanceNested);
}

bool LayoutComponent::animates()
{
    if (m_style == nullptr)
    {
        return false;
    }
    return 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;
    }
}

bool LayoutComponent::cascadeLayoutStyle(
    LayoutStyleInterpolation inheritedInterpolation,
    KeyFrameInterpolator* inheritedInterpolator,
    float inheritedInterpolationTime,
    LayoutDirection direction)
{
    bool updated = false;
    if (m_style != nullptr &&
        m_style->animationStyle() == LayoutAnimationStyle::inherit)
    {
        updated = setInheritedInterpolation(inheritedInterpolation,
                                            inheritedInterpolator,
                                            inheritedInterpolationTime);
    }
    else
    {
        clearInheritedInterpolation();
    }
    auto oldDirection = m_inheritedDirection;
    if (direction == LayoutDirection::inherit ||
        (m_style != nullptr && m_style->direction() != YGDirectionInherit))
    {
        m_inheritedDirection = LayoutDirection::inherit;
    }
    else
    {
        m_inheritedDirection = direction;
    }
    if (m_inheritedDirection != oldDirection)
    {
        markLayoutNodeDirty(true);
        addDirt(ComponentDirt::Path);
        updated = true;
    }
    for (auto child : children())
    {
        if (child->is<LayoutComponent>())
        {
            child->as<LayoutComponent>()->cascadeLayoutStyle(
                interpolation(),
                interpolator(),
                interpolationTime(),
                actualDirection());
        }
    }
    return updated;
}

bool LayoutComponent::setInheritedInterpolation(
    LayoutStyleInterpolation inheritedInterpolation,
    KeyFrameInterpolator* inheritedInterpolator,
    float inheritedInterpolationTime)
{
    if (inheritedInterpolation != m_inheritedInterpolation ||
        inheritedInterpolator != m_inheritedInterpolator ||
        inheritedInterpolationTime != m_inheritedInterpolationTime)
    {
        m_inheritedInterpolation = inheritedInterpolation;
        m_inheritedInterpolator = inheritedInterpolator;
        m_inheritedInterpolationTime = inheritedInterpolationTime;
        return true;
    }
    return false;
}

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

LayoutAnimationData* LayoutComponent::currentAnimationData()
{
    return m_isSmoothingAnimation ? &m_animationDataB : &m_animationDataA;
}

void LayoutAnimationData::copy(const LayoutAnimationData& source)
{
    from = source.from;
    to = source.to;
    elapsedSeconds = source.elapsedSeconds;
}

bool LayoutComponent::applyInterpolation(float elapsedSeconds, bool animate)
{
    auto animationData = currentAnimationData();
    if (!animate || !animates() || m_style == nullptr ||
        animationData->to == m_layout)
    {
        return false;
    }
    if (m_isSmoothingAnimation)
    {
        float f = std::fmin(1.0f,
                            interpolationTime() > 0.0f
                                ? m_animationDataA.elapsedSeconds /
                                      interpolationTime()
                                : 1.0f);

        if (interpolation() != LayoutStyleInterpolation::linear &&
            interpolator() != nullptr)
        {
            f = interpolator()->transform(f);
        }
        m_animationDataB.from = m_animationDataA.interpolate(f);
        if (f == 1.0f)
        {
            m_animationDataA.copy(m_animationDataB);
            m_isSmoothingAnimation = false;
        }
        else
        {
            m_animationDataA.elapsedSeconds += elapsedSeconds;
        }
    }

    if ((animationData = currentAnimationData())->elapsedSeconds >=
        interpolationTime())
    {
        Layout newLayout = animationData->to;
        if (m_layout.width() != newLayout.width() ||
            m_layout.height() != newLayout.height())
        {
            addDirt(ComponentDirt::Path);
        }
        m_layout = animationData->to;

        if (m_isSmoothingAnimation)
        {
            m_isSmoothingAnimation = false;
            m_animationDataA.copy(m_animationDataB);
            m_animationDataA.elapsedSeconds = m_animationDataB.elapsedSeconds =
                0.0f;
        }
        else
        {
            m_animationDataA.elapsedSeconds = 0.0f;
        }
        propagateSize();
        markWorldTransformDirty();

        return false;
    }
    float f =
        std::fmin(1.0f,
                  interpolationTime() > 0
                      ? animationData->elapsedSeconds / interpolationTime()
                      : 1.0f);
    if (interpolation() != LayoutStyleInterpolation::linear &&
        interpolator() != nullptr)
    {
        f = interpolator()->transform(f);
    }

    auto current = animationData->interpolate(f);
    if (m_layout != current)
    {
        bool sizeChanged = m_layout.width() != current.width() ||
                           m_layout.height() != current.height();
        m_layout = current;
        if (sizeChanged)
        {
            propagateSize();
        }
        markWorldTransformDirty();
    }

    animationData->elapsedSeconds += elapsedSeconds;
    if (f != 1)
    {
        // Do we really need to mark the layout node dirty!!??
        markLayoutNodeDirty();
        return true;
    }
    return false;
}

void LayoutComponent::interruptAnimation()
{
    if (animates())
    {
        m_layout = currentAnimationData()->to;
        propagateSize();
    }
}

void LayoutComponent::markLayoutNodeDirty(bool shouldForceUpdateLayoutBounds)
{
    if (shouldForceUpdateLayoutBounds == true)
    {
        m_forceUpdateLayoutBounds = shouldForceUpdateLayoutBounds;
    }
    m_layoutData->node.markDirtyAndPropagate();
    artboard()->markLayoutDirty(this);
}

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

void LayoutComponent::positionTypeChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    if (m_style->positionType() == YGPositionTypeAbsolute)
    {
        m_style->positionLeft(layoutBounds().left());
        m_style->positionTop(layoutBounds().top());
        m_style->positionRight(0);
        m_style->positionBottom(0);
        m_style->positionLeftUnitsValue(YGUnitPoint);
        m_style->positionTopUnitsValue(YGUnitPoint);
        m_style->positionRightUnitsValue(YGUnitUndefined);
        m_style->positionBottomUnitsValue(YGUnitUndefined);
    }
    else
    {
        m_style->positionLeft(0);
        m_style->positionTop(0);
        m_style->positionRight(0);
        m_style->positionBottom(0);
        m_style->positionLeftUnitsValue(YGUnitUndefined);
        m_style->positionTopUnitsValue(YGUnitUndefined);
        m_style->positionRightUnitsValue(YGUnitUndefined);
        m_style->positionBottomUnitsValue(YGUnitUndefined);
    }
    markLayoutNodeDirty();
}

void LayoutComponent::scaleTypeChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    m_style->widthUnitsValue(m_style->widthScaleType() == LayoutScaleType::fixed
                                 ? YGUnitPoint
                                 : YGUnitAuto);
    m_style->heightUnitsValue(
        m_style->heightScaleType() == LayoutScaleType::fixed ? YGUnitPoint
                                                             : YGUnitAuto);
    m_style->intrinsicallySizedValue(
        m_style->widthScaleType() == LayoutScaleType::hug ||
        m_style->heightScaleType() == LayoutScaleType::hug);
    markLayoutNodeDirty();
}

void LayoutComponent::displayChanged()
{
    if (m_style == nullptr)
    {
        return;
    }
    propagateCollapse(isCollapsed());
    markLayoutNodeDirty();
}

void LayoutComponent::flexDirectionChanged()
{
    markLayoutNodeDirty();
    for (Component* child : children())
    {
        auto layout = LayoutNodeProvider::from(child);
        if (layout != nullptr)
        {
            layout->markLayoutNodeDirty();
        }
    }
}

void LayoutComponent::directionChanged()
{
    markLayoutStyleDirty();
    markLayoutNodeDirty(true);
}
#else
LayoutComponent::LayoutComponent() :
    m_layoutData(new LayoutData()), m_proxy(this)
{}

float LayoutComponent::gapHorizontal() { return 0; }
float LayoutComponent::gapVertical() { return 0; }

void LayoutComponent::drawProxy(Renderer* renderer) {}

void LayoutComponent::draw(Renderer* renderer) {}

void LayoutComponent::updateRenderPath() {}

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode heightMode)
{
    return Vec2D();
}

bool LayoutComponent::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    return false;
}

void LayoutComponent::markLayoutNodeDirty(bool shouldForceUpdateLayoutBounds) {}
void LayoutComponent::markLayoutStyleDirty() {}
void LayoutComponent::onDirty(ComponentDirt value) {}
bool LayoutComponent::mainAxisIsRow() { return true; }

bool LayoutComponent::mainAxisIsColumn() { return false; }
void LayoutComponent::calculateLayoutInternal(float availableWidth,
                                              float availableHeight)
{}
#endif

LayoutComponent::~LayoutComponent()
{
    if (artboard() != nullptr)
    {
        artboard()->cleanLayout(this);
    }
#ifdef WITH_RIVE_TOOLS
    m_layoutData->unref();
#else
    delete m_layoutData;
#endif
}

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

ShapePaintPath* LayoutComponent::worldPath() { return &m_worldPath; }
ShapePaintPath* LayoutComponent::localPath() { return &m_localPath; }
ShapePaintPath* LayoutComponent::localClockwisePath() { return &m_localPath; }

Component* LayoutComponent::pathBuilder() { return this; }