#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/importers/import_stack.hpp"
#include "rive/intrinsically_sizeable.hpp"
#include "rive/layout_component.hpp"
#include "rive/component_origin.hpp"
#include "rive/layout/grid_track.hpp"
#include "rive/layout/layout_style_applier.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/node.hpp"
#include "rive/math/aabb.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/solo.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;

#ifdef WITH_RIVE_LAYOUT
void LayoutComponent::addLayoutStyleApplier(LayoutStyleApplier* applier)
{
    if (m_layoutData != nullptr)
    {
        m_layoutData->addApplier(applier);
    }
}
#endif

bool rive::isTransparentLayoutContainer(Component* component)
{
    return component->coreType() == NodeBase::typeKey || component->is<Solo>();
}

bool rive::joinsLayoutThroughContainer(Component* component)
{
    if (!component->is<ArtboardComponentList>())
    {
        return true;
    }
    auto flags =
        static_cast<DrawableFlag>(component->as<Drawable>()->drawableFlags());
    return (flags & DrawableFlag::ParticipatesInLayout) ==
           DrawableFlag::ParticipatesInLayout;
}

namespace
{
// Whether content-sizing stops here. Narrower than
// isTransparentLayoutContainer: a plain group is a barrier (its contents are
// free content), but a Solo is not — its children content-size just as direct
// children of the layout do.
bool stopsContentSizing(Component* component)
{
    return component->coreType() == NodeBase::typeKey;
}

// Visit every provider that belongs to a layout — its direct children, plus any
// nested inside transparent containers; depth-first, so layout order follows
// hierarchy order. Nested LayoutComponents and providers are leaves here (they
// own their subtree). Every child-walking layout pass goes through this, so a
// nested participant is collected, sized, cascaded and re-synced like a direct
// child.
template <typename F>
void forEachLayoutProvider(Component* from, F&& visit, bool nested = false)
{
    // A Solo only lets its active child through.
    if (from->is<Solo>())
    {
        if (auto* active = from->as<Solo>()->activeComponent())
        {
            if (auto* provider = LayoutNodeProvider::from(active))
            {
                if (!nested || joinsLayoutThroughContainer(active))
                {
                    visit(active, provider);
                }
            }
            else if (isTransparentLayoutContainer(active))
            {
                forEachLayoutProvider(active, visit, true);
            }
        }
        return;
    }
    for (auto* child : from->as<ContainerComponent>()->children())
    {
        if (auto* provider = LayoutNodeProvider::from(child))
        {
            if (!nested || joinsLayoutThroughContainer(child))
            {
                visit(child, provider);
            }
        }
        else if (isTransparentLayoutContainer(child))
        {
            forEachLayoutProvider(child, visit, true);
        }
    }
}

// Only reached when the HasComponentOrigin flag says one exists, so the common
// case never walks.
ComponentOrigin* originChild(const ContainerComponent* owner)
{
    for (auto* child : owner->children())
    {
        if (child->is<ComponentOrigin>())
        {
            return child->as<ComponentOrigin>();
        }
    }
    return nullptr;
}
} // namespace

LayoutComponent* rive::contentSizingLayout(Component* parent)
{
    for (Component* p = parent; p != nullptr; p = p->parent())
    {
        if (p->is<LayoutComponent>())
        {
            return p->as<LayoutComponent>();
        }
        // A group stops content sizing; a provider is sized by the engine.
        if (stopsContentSizing(p) || LayoutNodeProvider::from(p) != nullptr)
        {
            return nullptr;
        }
        auto* sizeable = IntrinsicallySizeable::from(p);
        if (sizeable != nullptr && !sizeable->shouldPropagateSizeToChildren())
        {
            return nullptr;
        }
    }
    return nullptr;
}

LayoutComponent* rive::owningLayout(Component* component)
{
    for (Component* p = component; p != nullptr; p = p->parent())
    {
        if (p->is<LayoutComponent>())
        {
            return p->as<LayoutComponent>();
        }
    }
    return nullptr;
}

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

float LayoutComponent::pivotOriginX() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin))
    {
        return 0.0f;
    }
    auto* origin = originChild(this);
    return origin != nullptr ? origin->originX() : 0.0f;
}

float LayoutComponent::pivotOriginY() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin))
    {
        return 0.0f;
    }
    auto* origin = originChild(this);
    return origin != nullptr ? origin->originY() : 0.0f;
}

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

void LayoutComponent::syncShapePaintBlendModes()
{
    for (auto paint : m_ShapePaints)
    {
        paint->blendMode(blendMode(), additiveAmount());
    }
}

// blendModeValue itself never animates, but additiveAmount does (and data
// binds), so the buildDependencies sync above is not enough on its own. Any
// ForegroundLayoutDrawable child re-reads us in its own draw().
void LayoutComponent::additiveAmountChanged() { syncShapePaintBlendModes(); }

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

StatusCode LayoutComponent::import(ImportStack& importStack)
{
    // Files exported before 7.3 composed a layout's transform from the solved
    // slot alone, so any stored rotation/scale was written but never applied.
    // Keep that legacy behavior for those files; newer files compose it on top
    // of the slot. See File::minorVersion.
    int major = importStack.majorVersion();
    int minor = importStack.minorVersion();
    setLayoutFlag(LayoutComponentFlags::ComposeTransform,
                  major > 7 || (major == 7 && minor >= 3));
    return Super::import(importStack);
}

Core* LayoutComponent::clone() const
{
    LayoutComponent* twin = LayoutComponentBase::clone()->as<LayoutComponent>();
    twin->setLayoutFlag(LayoutComponentFlags::ComposeTransform,
                        hasLayoutFlag(LayoutComponentFlags::ComposeTransform));
    // The clip-may-be-dynamic (KeyedObject::onAddedDirty) and listener-target
    // (StateMachineListener::onAddedClean) reasons for ForceDrawableProxy are
    // stamped only on the source, since instances share animations and state
    // machines. Carry the flag so an instance's proxy is still injected before
    // its first sort. (The scroll-interaction reason re-marks per instance in
    // buildDependencies, so carrying it here is a harmless no-op for that
    // case.)
    twin->setLayoutFlag(
        LayoutComponentFlags::ForceDrawableProxy,
        hasLayoutFlag(LayoutComponentFlags::ForceDrawableProxy));
    return twin;
}

bool LayoutComponent::composesLayoutOffset() const
{
    return hasLayoutFlag(LayoutComponentFlags::ComposeTransform) &&
           !is<Artboard>();
}

Vec2D LayoutComponent::localAnchor() const
{
    if (!hasLayoutFlag(LayoutComponentFlags::HasComponentOrigin) ||
        is<Artboard>())
    {
        return Vec2D();
    }
    return originOffset();
}

Vec2D LayoutComponent::originOffset() const
{
    return Vec2D(pivotOriginX() * m_layout.width(),
                 pivotOriginY() * m_layout.height());
}

Vec2D LayoutComponent::layoutTranslation() const
{
    // Our own origin deliberately does not enter here: contents sit within
    // our box whatever it is, so nothing inside has to compensate. An
    // artboard's origin does define where its local zero sits, so step back
    // by it to align to its box.
    auto location = Vec2D(m_layout.left(), m_layout.top());
    if (parent() != nullptr && parent()->is<Artboard>())
    {
        auto art = parent()->as<Artboard>();
        location -= Vec2D(art->layoutWidth() * art->originX(),
                          art->layoutHeight() * art->originY());
    }
    return location;
}

Mat2D LayoutComponent::buildOwnTransform() const
{
    // Outermost, matching TransformComponent's T * R * S, so the offset is
    // not rotated or scaled by our own transform.
    Mat2D own =
        composesLayoutOffset()
            ? Mat2D::fromTranslation(Vec2D(NodeBase::x(), NodeBase::y()))
            : Mat2D();

    // Pivot about the origin. The box stays put, so wrap rather than fold
    // into the frame.
    if (hasLayoutFlag(LayoutComponentFlags::ComposeTransform) &&
        (rotation() != 0.0f || scaleX() != 1.0f || scaleY() != 1.0f))
    {
        Mat2D local =
            rotation() != 0.0f ? Mat2D::fromRotation(rotation()) : Mat2D();
        local.scaleByValues(scaleX(), scaleY());
        auto pivot = originOffset();
        if (pivot.x != 0.0f || pivot.y != 0.0f)
        {
            local = Mat2D::multiply(
                Mat2D::fromTranslate(pivot.x, pivot.y),
                Mat2D::multiply(local,
                                Mat2D::fromTranslate(-pivot.x, -pivot.y)));
        }
        own = Mat2D::multiply(own, local);
    }
    return own;
}

// Same unrooted guard as Node's — nothing to be relative to yet.
float LayoutComponent::computedRootX()
{
    if (artboard() == nullptr)
    {
        return 0.0f;
    }
    return artboard()->rootTransform(worldTransform() * localAnchor()).x;
}

float LayoutComponent::computedRootY()
{
    if (artboard() == nullptr)
    {
        return 0.0f;
    }
    return artboard()->rootTransform(worldTransform() * localAnchor()).y;
}

void LayoutComponent::updateTransform() { m_Transform = buildOwnTransform(); }

void LayoutComponent::composeWorldTransform()
{
    Mat2D parentWorld =
        parent() != nullptr && parent()->is<WorldTransformComponent>()
            ? parent()->as<WorldTransformComponent>()->worldTransform()
            : Mat2D();
    // Insert where the layout placed us, the same shape Shape/Text/Image
    // use for a participant.
    Mat2D base = Mat2D::fromTranslation(layoutTranslation());
    m_WorldTransform =
        Mat2D::multiply(Mat2D::multiply(parentWorld, base), m_Transform);
}

void LayoutComponent::update(ComponentDirt value)
{
#ifdef WITH_RIVE_LAYOUT
    if (value == ComponentDirt::Filthy)
    {
        // First update: jump straight to the layout's target instead of
        // animating in from zero. Done before Super's pass below, which
        // composes our world transform from m_layout.
        interruptAnimation();
    }
#endif
    // m_Transform rotates and scales us about our origin, which sits at a
    // fraction of our solved size (see buildOwnTransform). A new layout solve
    // marks only WorldTransform dirty, so also pass Transform dirt: Super then
    // rebuilds m_Transform before it composes the world transform and applies
    // our constraints. Don't add a second pass after it -- ScrollConstraint
    // counts the children it constrains to decide when to virtualize.
    Super::update(parent() != nullptr &&
                          hasDirt(value, ComponentDirt::WorldTransform)
                      ? value | ComponentDirt::Transform
                      : value);
    if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        propagateOpacity(childOpacity());
    }
    if (hasDirt(value,
                ComponentDirt::Path | ComponentDirt::WorldTransform |
                    ComponentDirt::LayoutStyle))
    {
        updateRenderPath();
    }

    setLayoutFlag(LayoutComponentFlags::PositionLeftChanged, false);
    setLayoutFlag(LayoutComponentFlags::PositionTopChanged, false);
}

void LayoutComponent::widthOverride(float width, int unitValue, bool isRow)
{
    m_widthOverride = width;
    m_widthUnitValueOverride = static_cast<int8_t>(unitValue);
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

void LayoutComponent::heightOverride(float height, int unitValue, bool isRow)
{
    m_heightOverride = height;
    m_heightUnitValueOverride = static_cast<int8_t>(unitValue);
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

void LayoutComponent::parentIsRow(bool isRow)
{
    setLayoutFlag(LayoutComponentFlags::ParentIsRow, isRow);
    markLayoutNodeDirty();
}

#ifdef WITH_RIVE_LAYOUT
LayoutScaleType LayoutComponent::effectiveWidthScaleType()
{
    if (canHaveOverrides() && m_widthUnitValueOverride != -1)
    {
        switch (YGUnit(m_widthUnitValueOverride))
        {
            case YGUnitPoint:
            case YGUnitPercent:
                return LayoutScaleType::fixed;
            case YGUnitAuto:
                return hasLayoutFlag(
                           LayoutComponentFlags::WidthIntrinsicallySizeOverride)
                           ? LayoutScaleType::hug
                           : LayoutScaleType::fill;
            default:
                break;
        }
    }
    return m_style != nullptr ? m_style->widthScaleType()
                              : LayoutScaleType::fixed;
}

LayoutScaleType LayoutComponent::effectiveHeightScaleType()
{
    if (canHaveOverrides() && m_heightUnitValueOverride != -1)
    {
        switch (YGUnit(m_heightUnitValueOverride))
        {
            case YGUnitPoint:
            case YGUnitPercent:
                return LayoutScaleType::fixed;
            case YGUnitAuto:
                return hasLayoutFlag(LayoutComponentFlags::
                                         HeightIntrinsicallySizeOverride)
                           ? LayoutScaleType::hug
                           : LayoutScaleType::fill;
            default:
                break;
        }
    }
    return m_style != nullptr ? m_style->heightScaleType()
                              : LayoutScaleType::fixed;
}
#endif

void LayoutComponent::parentIsStack(bool isStack)
{
    if (hasLayoutFlag(LayoutComponentFlags::ParentIsStack) == isStack)
    {
        return;
    }
    setLayoutFlag(LayoutComponentFlags::ParentIsStack, isStack);
    markLayoutNodeDirty();
}

void LayoutComponent::widthIntrinsicallySizeOverride(bool intrinsic)
{
    setLayoutFlag(LayoutComponentFlags::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)
{
    setLayoutFlag(LayoutComponentFlags::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 (layoutConstraints().size() > 0)
    {
        for (auto parentConstraint : 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)
{
    auto collapsed = collapse || isCollapsed();
    for (Component* child : children())
    {
        child->collapse(collapsed);
    }
    updateCollapsables();
}

bool LayoutComponent::collapse(bool value)
{
    if (!Component::collapse(value))
    {
        return false;
    }
    propagateCollapse(value);
    return true;
}

#ifdef WITH_RIVE_LAYOUT

LayoutComponent::LayoutComponent() : m_layoutData(new LayoutData())
{
    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);
#ifdef WITH_RIVE_LAYOUT
    refreshStyleDisplayHidden();
    // We contribute sizing the style cannot see; it contributes the rest.
    addLayoutStyleApplier(this);
    addLayoutStyleApplier(m_style);
#endif

    return StatusCode::Ok;
}

StatusCode LayoutComponent::onAddedClean(CoreContext* context)
{
    auto code = Super::onAddedClean(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
#ifdef WITH_RIVE_EDITOR
    // Coop-apply hydration: skip the render/layout side effects — the
    // graph is partial here and they re-fire when the renderer attaches
    // and the first pump runs. Runtime .riv imports are marked validated
    // at read time and never see a pump, so they must run the wiring now
    // or Yoga layout stays NaN.
    if (hasValidated())
#endif
    {
        markLayoutStyleDirty();
        syncLayoutChildren();
        propagateCollapse(isCollapsed());
    }
    return StatusCode::Ok;
}

void LayoutComponent::drawProxy(Renderer* renderer)
{
    // Pair the save/clip here with the restore in draw(). Record whether we
    // actually saved so draw() never restores a save that wasn't issued. Set OR
    // clear it every time the proxy draws: the proxy is injected once and stays
    // in the draw order, so a later pass where clip() is off must clear a stale
    // true from an earlier pass. (When the proxy isn't in the draw order at
    // all, this never runs, the flag stays false, and draw() skips the
    // restore.)
    const bool saveForClip = clip();
    if (saveForClip)
    {
        renderer->save();
        renderer->clipPath(mutableRenderPaths().world.renderPath(this));
    }
    setLayoutFlag(LayoutComponentFlags::ClipSaved, saveForClip);
    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. Pair the
    // restore with drawProxy()'s save via ClipSaved rather than clip(): if the
    // proxy wasn't in the draw order (so drawProxy() never saved) but clip() is
    // true, restoring here would underflow the renderer's save stack.
    if (hasLayoutFlag(LayoutComponentFlags::ClipSaved))
    {
        setLayoutFlag(LayoutComponentFlags::ClipSaved, false);
        renderer->restore();
    }
}

void LayoutComponent::updateRenderPath()
{
    if (isHidden())
    {
        return;
    }
    if (m_ShapePaints.empty() && !clip() &&
        !hasLayoutFlag(LayoutComponentFlags::HasForegroundDrawable))
    {
        return;
    }
    float tl = 0.0f, tr = 0.0f, br = 0.0f, bl = 0.0f;
    if (style() != nullptr)
    {
        const bool isLTR = actualDirection() != LayoutDirection::rtl;
        if (style()->linkCornerRadius())
        {
            tl = tr = br = bl = style()->cornerRadiusTL();
        }
        else
        {
            tl = isLTR ? style()->cornerRadiusTL() : style()->cornerRadiusTR();
            tr = isLTR ? style()->cornerRadiusTR() : style()->cornerRadiusTL();
            bl = isLTR ? style()->cornerRadiusBL() : style()->cornerRadiusBR();
            br = isLTR ? style()->cornerRadiusBR() : style()->cornerRadiusBL();
        }
    }

    auto& renderPaths = mutableRenderPaths();
    renderPaths.background.rewind();
    Path::addRoundedRect(
        renderPaths.background,
        AABB::fromLTWH(0.0f, 0.0f, m_layout.width(), m_layout.height()),
        tl,
        tr,
        br,
        bl);
    // Drop empty segments, such as the zero-length sides of a pill. local's
    // addPath would drop them anyway; doing it here makes local an exact copy
    // of the background, so the two can be compared below.
    renderPaths.background.pruneEmptySegments();

    // Moving a layout leaves its background as it was. Keep local then:
    // rewinding it would hand the renderer identical geometry and discard the
    // tessellation it cached for it. Compare rather than trust the dirt that
    // got us here: a layout tween resizes with only WorldTransform dirt. world
    // always rebuilds, since it bakes in the world transform.
    if (!(*renderPaths.local.rawPath() == renderPaths.background))
    {
        renderPaths.local.rewind();
        renderPaths.local.addPath(renderPaths.background);
    }

    renderPaths.world.rewind(false, FillRule::clockwise);
    renderPaths.world.addPath(renderPaths.background, &m_WorldTransform);

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

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

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

Vec2D LayoutComponent::measureLayout(float width,
                                     LayoutMeasureMode widthMode,
                                     float height,
                                     LayoutMeasureMode heightMode)
{
    if (m_style != nullptr && m_style->hugUnbounded())
    {
        // Per axis: a fill axis leaves flexBasis auto, so its measure feeds
        // yoga's basis for the line. Widening it there would move this item's
        // share of the remainder -- a fill axis the option never promised to
        // touch.
        bool widthHugs = effectiveWidthScaleType() == LayoutScaleType::hug;
        bool heightHugs = effectiveHeightScaleType() == LayoutScaleType::hug;
        // Legacy files encode hug as fixed on BOTH axes plus
        // intrinsicallySized.
        if (!widthHugs && !heightHugs)
        {
            widthHugs = heightHugs = m_style->intrinsicallySized();
        }
        if (widthHugs)
        {
            widthMode = unboundMeasureMode(widthMode);
        }
        if (heightHugs)
        {
            heightMode = unboundMeasureMode(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::effectiveParentIsRow()
{
    if (canHaveOverrides())
    {
        return hasLayoutFlag(LayoutComponentFlags::ParentIsRow);
    }
    return layoutParent() != nullptr ? layoutParent()->mainAxisIsRow() : true;
}

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::isStackContainer()
{
    return style() != nullptr && style()->isStack();
}

bool LayoutComponent::isLeaf()
{
    bool leaf = true;
    forEachLayoutProvider(this, [&leaf](Component*, LayoutNodeProvider*) {
        leaf = false;
    });
    return leaf;
}

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

#ifdef WITH_RIVE_LAYOUT
// Tracks come from GridTrack children, which the style cannot walk. A stack has
// no authored tracks — the style sets up its implicit cell instead.
void LayoutComponent::applyContainerStyle(YGStyle& ygStyle,
                                          const LayoutSyncContext& context)
{
    if (m_style == nullptr || m_style->isStack())
    {
        return;
    }
    GridTrack::syncContainerStyle(ygStyle, this, m_style->justifyItemsValue());
}
#endif

#ifdef WITH_RIVE_LAYOUT
// This layout's own size and how it sits in its parent's flow. On the
// component, not the style, because it reads width()/height(), the
// NestedArtboardLayout overrides and the forced dimensions.
//
// Not shared with LayoutParticipant::applyBaseStyle: the participant has no
// flexBasis, no overrides and its own fractionalWidth, so merging would change
// behaviour.
void LayoutComponent::applyBaseStyle(YGStyle& ygStyle,
                                     const LayoutSyncContext& context)
{
    if (m_style == nullptr)
    {
        return;
    }
    const bool parentIsRow = context.parentIsRow;
    const bool parentIsGridLike = context.parentIsGrid;

    // Derive the unit the layout engine needs from the persisted unit + scale
    // type.
    //   - fill/hug always map to YGUnitAuto (regardless of position type) —
    //     these scale modes don't have a meaningful unit; the layout engine
    //     decides the size.
    //   - fixed uses the stored unit. Absolute layouts trust whatever's
    //     stored (e.g. the editor freezes a point value at the moment
    //     positionType becomes absolute, since absolute children sit outside
    //     flex flow).
    bool isAbsolute = m_style->positionType() == YGPositionTypeAbsolute;
    bool isLegacyHugEncoding =
        m_style->widthScaleType() == LayoutScaleType::fixed &&
        m_style->heightScaleType() == LayoutScaleType::fixed &&
        m_style->intrinsicallySized() && isLeaf();
    auto effectiveUnits = [isAbsolute,
                           isLegacyHugEncoding](LayoutScaleType scaleType,
                                                YGUnit storedUnits) {
        if (isAbsolute && scaleType != LayoutScaleType::hug)
        {
            return storedUnits;
        }
        if (scaleType != LayoutScaleType::fixed)
        {
            return YGUnitAuto;
        }
        if (storedUnits == YGUnitPoint || storedUnits == YGUnitPercent)
        {
            return storedUnits;
        }
        return isLegacyHugEncoding ? YGUnitAuto : YGUnitPoint;
    };
    auto realWidth = width();
    auto realWidthScaleType = m_style->widthScaleType();
    auto realWidthUnits =
        effectiveUnits(realWidthScaleType, m_style->widthUnits());
    auto realHeight = height();
    auto realHeightScaleType = m_style->heightScaleType();
    auto realHeightUnits =
        effectiveUnits(realHeightScaleType, m_style->heightUnits());

    // 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;
        }
        if (m_widthUnitValueOverride != -1)
        {
            realWidthUnits = YGUnit(m_widthUnitValueOverride);
            realWidthScaleType = effectiveWidthScaleType();
        }
        if (m_heightUnitValueOverride != -1)
        {
            realHeightUnits = YGUnit(m_heightUnitValueOverride);
            realHeightScaleType = effectiveHeightScaleType();
        }
    }
    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};
    }

    if (parentIsGridLike)
    {
        // Grid/stack: size per-axis. fill stretches that axis (width ->
        // justifySelf after grid placement below, height -> alignSelf);
        // non-fill stays auto so the container alignment positions us. flexGrow
        // ignored.
        ygStyle.flexGrow() = YGFloatOptional(0);
        ygStyle.flexShrink() = YGFloatOptional(0);
        ygStyle.alignSelf() = realHeightScaleType == LayoutScaleType::fill
                                  ? YGAlignStretch
                                  : YGAlignAuto;
    }
    else
    {
        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;
        }
    }
}
#endif

void LayoutComponent::syncStyle()
{
    if (m_style == nullptr || m_layoutData == nullptr)
    {
        return;
    }
    YGNode& ygNode = m_layoutData->node;
    // Appliers write straight into the node's own style; no scratch copy.
    YGStyle& ygStyle = m_layoutData->style();
    if (m_style->intrinsicallySized() && isLeaf())
    {
        ygNode.setContext(this);
        ygNode.setMeasureFunc(measureFunc);
    }
    else
    {
        ygNode.setMeasureFunc(nullptr);
    }

    // Our owning layout may sit above a transparent container (group/Solo), so
    // walk up for it rather than reading the immediate parent — a grouped item
    // is still laid out by the container and needs its context. Cached because
    // layoutParent() walks the chain on each call.
    auto* parentLayout = layoutParent();
    auto* parentLayoutStyle =
        parentLayout != nullptr ? parentLayout->style() : nullptr;
    // A hosted artboard (list item, nested artboard layout) has no parent() to
    // walk, so its host pushes the container's stack state in. Only stack is
    // pushed: a grid already auto-places these nodes correctly, and claiming
    // grid here would move them off the flex sizing path they use today.
    bool parentIsStack =
        parentLayoutStyle != nullptr
            ? parentLayoutStyle->isStack()
            : (canHaveOverrides() &&
               hasLayoutFlag(LayoutComponentFlags::ParentIsStack));
    bool parentIsGridLike = parentLayoutStyle != nullptr
                                ? parentLayoutStyle->isGrid()
                                : parentIsStack;
    uint32_t containerJustifyItems =
        parentLayoutStyle != nullptr ? parentLayoutStyle->justifyItemsValue()
                                     : (uint32_t)YGJustifyStretch;
    // Every style write is an applier now; resolve the context and run them.
    LayoutSyncContext syncContext;
    syncContext.parentIsGrid = parentIsGridLike;
    syncContext.parentIsStack = parentIsStack;
    syncContext.containerJustifyItems = containerJustifyItems;
    auto widthScale = effectiveWidthScaleType();
    syncContext.widthFills = widthScale == LayoutScaleType::fill;
    syncContext.inlineHugs = widthScale == LayoutScaleType::hug;
    syncContext.parentIsRow = effectiveParentIsRow();
    syncContext.isLTR = actualDirection() != LayoutDirection::rtl;
    syncContext.hasLayoutParent = layoutParent() != nullptr;
    m_layoutData->applyLayoutStyles(ygStyle, syncContext);

    // Sync the styles of participant children that provide their
    // own layout node (including any nested inside transparent groups).
    // LayoutComponent children sync their own styles through the dirty-layout
    // set; these have no such entry.
    forEachLayoutProvider(this,
                          [](Component* child, LayoutNodeProvider* provider) {
                              switch (child->coreType())
                              {
                                  case LayoutComponentBase::typeKey:
                                  case NestedArtboardLayoutBase::typeKey:
                                  case ArtboardComponentListBase::typeKey:
                                      break;
                                  default:
                                      provider->syncStyleChanges();
                                      break;
                              }
                          });
}

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

void LayoutComponent::syncLayoutChildren()
{
    YGNode& ourNode = m_layoutData->node;
    YGNodeRemoveAllChildren(&ourNode);
    int index = 0;
    forEachLayoutProvider(
        this,
        [&ourNode, &index](Component*, LayoutNodeProvider* provider) {
            for (size_t i = 0; i < provider->numLayoutNodes(); i++)
            {
                auto* node = static_cast<YGNode*>(provider->layoutNode((int)i));
                if (node != nullptr)
                {
                    ourNode.insertChild(node, index++);
                    node->setOwner(&ourNode);
                    ourNode.markDirtyAndPropagate();
                }
            }
        });
    markLayoutNodeDirty();
}

#ifdef WITH_RIVE_TOOLS
bool LayoutComponent::collectsForLayout(Component* child)
{
    // Runs the real walk rather than a copy of the rule.
    bool found = false;
    forEachLayoutProvider(this,
                          [child, &found](Component* c, LayoutNodeProvider*) {
                              if (c == child)
                              {
                                  found = true;
                              }
                          });
    return found;
}
#endif

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

void LayoutComponent::propagateSizeToChildren(ContainerComponent* component)
{
    if (isHidden())
    {
        return;
    }
    for (auto child : component->children())
    {
        // Don't content-size nested layouts, or groups — a group's contents are
        // free content, never content-sized from here. A Solo is not a barrier:
        // its children content-size as direct children would. A participating
        // child is caught by the provider check below.
        if (child->is<LayoutComponent>() || stopsContentSizing(child))
        {
            continue;
        }
        // A participating child owns its own layout node and is sized by the
        // layout engine, not by controlSize — skip it.
        if (LayoutNodeProvider::from(child) != nullptr)
        {
            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
{
#ifdef WITH_RIVE_EDITOR
    // The editor can change a style under us without telling this layout, so
    // read it every time there.
    return m_style != nullptr && m_style->display() == YGDisplayNone;
#else
    return hasLayoutFlag(LayoutComponentFlags::StyleDisplayHidden);
#endif
}

void LayoutComponent::refreshStyleDisplayHidden()
{
    setLayoutFlag(LayoutComponentFlags::StyleDisplayHidden,
                  m_style != nullptr && 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);

    forEachLayoutProvider(this,
                          [animate](Component*, LayoutNodeProvider* provider) {
                              provider->updateLayoutBounds(animate);
                          });

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

    if (hasLayoutFlag(LayoutComponentFlags::JustAddedToHost))
    {
        setLayoutFlag(LayoutComponentFlags::JustAddedToHost, false);
        // In cases were we have a host (ie, Component List, etc), we
        // don't want to animate the x/y/width/height because the initial
        // x/y/width/height will have been 0,0,0,0 within the parent host.
        //
        // Instead, we want to the position/size to start at whatever this
        // layout's computed position is within its host.
        //
        // We'll keep this as an entirely seperate code path because
        // this may be useful in adding support for animate in/out of
        // items in an ArtboardHost.
        m_layout = newLayout;
        // Unallocated, from/to already read as m_layout, which we just set --
        // there is nothing to snap.
        if (auto* animationData = currentAnimationData())
        {
            animationData->from = newLayout;
            animationData->to = newLayout;
            animationData->elapsedSeconds = 0.0f;
        }
        propagateSize();
        markWorldTransformDirty();
        setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds, false);
        return;
    }

    if (animate && animates())
    {
        // Test the target before allocating: with no state the target reads
        // as m_layout, so a layout that solves to the bounds it already has
        // never pays for the block just because its style can animate.
        auto animationData = currentAnimationData();
        const Layout& target =
            animationData != nullptr ? animationData->to : m_layout;
        if (newLayout != target ||
            hasLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds))
        {
            // Committed to retargeting now, so realize the state.
            ensureAnimation();
            animationData = currentAnimationData();
            if (animationData->elapsedSeconds != 0.0f)
            {
                if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
                {
                    // we were already smoothening.
                    m_animation->a.copy(m_animation->b);
                }
                setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, true);
            }
            else
            {
                setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation,
                              false);
            }
            animationData = currentAnimationData();
            animationData->from = m_layout;
            animationData->to = newLayout;
            animationData->elapsedSeconds = 0.0f;
            propagateSize();
            markWorldTransformDirty();
        }
    }
    else if (newLayout != m_layout ||
             hasLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds))
    {
        if (m_layout.width() != newLayout.width() ||
            m_layout.height() != newLayout.height())
        {
            // Width changed, we need to rebuild the path.
            addDirt(ComponentDirt::Path);
        }
        m_layout = newLayout;
        if (m_animation != nullptr)
        {
            // Keep the animate path's retarget check honest: while we are not
            // animating, `to` tracks m_layout (which is what the unallocated
            // case reports anyway).
            m_animation->a.to = newLayout;
        }

        propagateSize();
        markWorldTransformDirty();
    }
    setLayoutFlag(LayoutComponentFlags::ForceUpdateLayoutBounds, false);
}

AdvancingComponent::QuietState LayoutComponent::quietState()
{
    // The early outs of advanceComponent and applyInterpolation.
    auto animationData = currentAnimationData();
    if (isCollapsed() || animationData == nullptr || !animates() ||
        m_style == nullptr || animationData->to == m_layout)
    {
        return QuietState::quiet;
    }
    return QuietState::busy;
}

bool LayoutComponent::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
{
    if ((flags & AdvanceFlags::NewFrame) != AdvanceFlags::NewFrame ||
        isCollapsed())
    {
        return false;
    }

    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:
        {
            auto* inherited = m_animation != nullptr
                                  ? m_animation->inheritedInterpolator
                                  : nullptr;
            return inherited != nullptr ? inherited : 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_animation != nullptr ? m_animation->inheritedInterpolation
                                          : defaultInterpolation;
        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_animation != nullptr
                       ? m_animation->inheritedInterpolationTime
                       : 0;
        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;
    }
    forEachLayoutProvider(this,
                          [this](Component*, LayoutNodeProvider* provider) {
                              provider->cascadeLayoutStyle(interpolation(),
                                                           interpolator(),
                                                           interpolationTime(),
                                                           actualDirection());
                          });
    return updated;
}

bool LayoutComponent::setInheritedInterpolation(
    LayoutStyleInterpolation inheritedInterpolation,
    KeyFrameInterpolator* inheritedInterpolator,
    float inheritedInterpolationTime)
{
    if (m_animation == nullptr)
    {
        // An all-default cascade is what an unallocated layout already
        // reports, so storing it would change nothing but the footprint.
        if (inheritedInterpolation == LayoutStyleInterpolation::hold &&
            inheritedInterpolator == nullptr &&
            inheritedInterpolationTime == 0.0f)
        {
            return false;
        }
        ensureAnimation();
    }
    if (inheritedInterpolation != m_animation->inheritedInterpolation ||
        inheritedInterpolator != m_animation->inheritedInterpolator ||
        inheritedInterpolationTime != m_animation->inheritedInterpolationTime)
    {
        m_animation->inheritedInterpolation = inheritedInterpolation;
        m_animation->inheritedInterpolator = inheritedInterpolator;
        m_animation->inheritedInterpolationTime = inheritedInterpolationTime;
        return true;
    }
    return false;
}

void LayoutComponent::clearInheritedInterpolation()
{
    if (m_animation == nullptr)
    {
        // Already reporting the cleared values.
        return;
    }
    m_animation->inheritedInterpolation = LayoutStyleInterpolation::hold;
    m_animation->inheritedInterpolator = nullptr;
    m_animation->inheritedInterpolationTime = 0;
}

LayoutAnimationData* LayoutComponent::currentAnimationData()
{
    if (m_animation == nullptr)
    {
        return nullptr;
    }
    return hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation)
               ? &m_animation->b
               : &m_animation->a;
}

LayoutAnimation& LayoutComponent::ensureAnimation()
{
    if (m_animation == nullptr)
    {
        m_animation = std::make_unique<LayoutAnimation>();
        // While unallocated the accessors report from/to as m_layout. Seed the
        // real state identically so realizing it is never observable -- in
        // particular the animate path's `newLayout != to` retarget check must
        // not fire just because we allocated.
        m_animation->a.from = m_animation->a.to = m_layout;
        m_animation->b.from = m_animation->b.to = m_layout;
    }
    return *m_animation;
}

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();
    // No state means nothing was ever retargeted: `to` reads as m_layout, so
    // the original `to == m_layout` bail-out holds by construction.
    if (animationData == nullptr || !animate || !animates() ||
        m_style == nullptr || animationData->to == m_layout)
    {
        return false;
    }
    if (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
    {
        float f =
            std::fmin(1.0f,
                      interpolationTime() > 0.0f
                          ? m_animation->a.elapsedSeconds / interpolationTime()
                          : 1.0f);

        if (interpolation() != LayoutStyleInterpolation::linear &&
            interpolator() != nullptr)
        {
            f = interpolator()->transform(f);
        }
        m_animation->b.from = m_animation->a.interpolate(f);
        if (f == 1.0f)
        {
            m_animation->a.copy(m_animation->b);
            setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, false);
        }
        else
        {
            m_animation->a.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 (hasLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation))
        {
            setLayoutFlag(LayoutComponentFlags::IsSmoothingAnimation, false);
            m_animation->a.copy(m_animation->b);
            m_animation->a.elapsedSeconds = m_animation->b.elapsedSeconds =
                0.0f;
        }
        else
        {
            m_animation->a.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)
    {
        // The tween moves m_layout toward a target the last solve already
        // produced, and changes nothing Yoga reads, so a layout needs no new
        // solve while it runs. An artboard is the exception: a host that lays
        // it out (a list, a nested artboard layout) only learns its new size
        // through markLayoutDirty, which markLayoutNodeDirty calls.
        if (is<Artboard>())
        {
            markLayoutNodeDirty();
        }
        return true;
    }
    return false;
}

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

void LayoutComponent::markLayoutNodeDirty(bool shouldForceUpdateLayoutBounds)
{
    if (shouldForceUpdateLayoutBounds == true)
    {
        setLayoutFlag(LayoutComponentFlags::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)
    {
        // Preserve computed position only if left/top were not explicitly keyed
        // this frame. If keyed, honor those values and only set units
        // appropriately.
        if (!hasLayoutFlag(LayoutComponentFlags::PositionLeftChanged))
        {
            m_style->positionLeft(layoutBounds().left());
        }
        if (!hasLayoutFlag(LayoutComponentFlags::PositionTopChanged))
        {
            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->intrinsicallySizedValue(
        m_style->widthScaleType() == LayoutScaleType::hug ||
        m_style->heightScaleType() == LayoutScaleType::hug);
    markLayoutNodeDirty();
}

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

void LayoutComponent::syncChildProviderStyles()
{
    forEachLayoutProvider(this, [](Component*, LayoutNodeProvider* provider) {
        provider->syncStyleChanges();
        provider->markLayoutNodeDirty();
    });
}

void LayoutComponent::flexDirectionChanged()
{
    markLayoutNodeDirty();
    syncChildProviderStyles();
}

// Switching grid/flex/stack changes how each child's style maps to yoga.
void LayoutComponent::layoutTypeChanged()
{
    markLayoutNodeDirty();
    syncChildProviderStyles();
}

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

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

AdvancingComponent::QuietState LayoutComponent::quietState()
{
    return QuietState::quiet;
}

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

bool LayoutComponent::mainAxisIsColumn() { return false; }
bool LayoutComponent::isStackContainer() { 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();
    addDirt(ComponentDirt::Path);
}
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_renderPaths != nullptr ? &m_renderPaths->world : nullptr;
}
ShapePaintPath* LayoutComponent::localPath()
{
    return m_renderPaths != nullptr ? &m_renderPaths->local : nullptr;
}
ShapePaintPath* LayoutComponent::localClockwisePath()
{
    return m_renderPaths != nullptr ? &m_renderPaths->local : nullptr;
}

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

BoundsFidelity LayoutComponent::paintedWorldBounds(AABB* out)
{
    // localBounds() through worldTransform(), deliberately NOT worldBounds():
    // that one reads only transform[4] and [5], so it silently drops rotation
    // and scale and would under-report a rotated layout.
    //
    // Corner radius and clip() only ever shrink what is painted, so ignoring
    // both keeps this an over-estimate.
    return paintedBoundsFromLocal(localBounds(), worldTransform(), this, out);
}
