// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

import 'basic.dart';
import 'framework.dart';

/// Defines the horizontal alignment of [OverflowBar] children
/// when they're laid out in an overflow column.
///
/// This value must be interpreted relative to the ambient
/// [TextDirection].
enum OverflowBarAlignment {
  /// Each child is left-aligned for [TextDirection.ltr],
  /// right-aligned for [TextDirection.rtl].
  start,

  /// Each child is right-aligned for [TextDirection.ltr],
  /// left-aligned for [TextDirection.rtl].
  end,

  /// Each child is horizontally centered.
  center,
}

/// A widget that lays out its [children] in a row unless they
/// "overflow" the available horizontal space, in which case it lays
/// them out in a column instead.
///
/// This widget's width will expand to contain its children and the
/// specified [spacing] until it overflows. The overflow column will
/// consume all of the available width.  The [overflowAlignment]
/// defines how each child will be aligned within the overflow column
/// and the [overflowSpacing] defines the gap between each child.
///
/// The order that the children appear in the horizontal layout
/// is defined by the [textDirection], just like the [Row] widget.
/// If the layout overflows, then children's order within their
/// column is specified by [overflowDirection] instead.
///
/// {@tool dartpad}
/// This example defines a simple approximation of a dialog
/// layout, where the layout of the dialog's action buttons are
/// defined by an [OverflowBar]. The content is wrapped in a
/// [SingleChildScrollView], so that if overflow occurs, the
/// action buttons will still be accessible by scrolling,
/// no matter how much vertical space is available.
///
/// ** See code in examples/api/lib/widgets/overflow_bar/overflow_bar.0.dart **
/// {@end-tool}
class OverflowBar extends MultiChildRenderObjectWidget {
  /// Constructs an OverflowBar.
  ///
  /// The [spacing], [overflowSpacing], [overflowAlignment],
  /// [overflowDirection], and [clipBehavior] parameters must not be
  /// null. The [children] argument must not be null and must not contain
  /// any null objects.
  OverflowBar({
    Key? key,
    this.spacing = 0.0,
    this.alignment,
    this.overflowSpacing = 0.0,
    this.overflowAlignment = OverflowBarAlignment.start,
    this.overflowDirection = VerticalDirection.down,
    this.textDirection,
    this.clipBehavior = Clip.none,
    List<Widget> children = const <Widget>[],
  }) : assert(spacing != null),
       assert(overflowSpacing != null),
       assert(overflowAlignment != null),
       assert(overflowDirection != null),
       assert(clipBehavior != null),
       super(key: key, children: children);

  /// The width of the gap between [children] for the default
  /// horizontal layout.
  ///
  /// If the horizontal layout overflows, then [overflowSpacing] is
  /// used instead.
  ///
  /// Defaults to 0.0.
  final double spacing;

  /// Defines the [children]'s horizontal layout according to the same
  /// rules as for [Row.mainAxisAlignment].
  ///
  /// If this property is non-null, and the [children], separated by
  /// [spacing], fit within the available width, then the overflow
  /// bar will be as wide as possible. If the children do not fit
  /// within the available width, then this property is ignored and
  /// [overflowAlignment] applies instead.
  ///
  /// If this property is null (the default) then the overflow bar
  /// will be no wider than needed to layout the [children] separated
  /// by [spacing], modulo the incoming constraints.
  ///
  /// If [alignment] is one of [MainAxisAlignment.spaceAround],
  /// [MainAxisAlignment.spaceBetween], or
  /// [MainAxisAlignment.spaceEvenly], then the [spacing] parameter is
  /// only used to see if the horizontal layout will overflow.
  ///
  /// Defaults to null.
  ///
  /// See also:
  ///
  ///  * [overflowAlignment], the horizontal alignment of the [children] within
  ///    the vertical "overflow" layout.
  ///
  final MainAxisAlignment? alignment;

  /// The height of the gap between [children] in the vertical
  /// "overflow" layout.
  ///
  /// This parameter is only used if the horizontal layout overflows, i.e.
  /// if there isn't enough horizontal room for the [children] and [spacing].
  ///
  /// Defaults to 0.0.
  ///
  /// See also:
  ///
  ///  * [spacing], The width of the gap between each pair of children
  ///    for the default horizontal layout.
  final double overflowSpacing;

  /// The horizontal alignment of the [children] within the vertical
  /// "overflow" layout.
  ///
  /// This parameter is only used if the horizontal layout overflows, i.e.
  /// if there isn't enough horizontal room for the [children] and [spacing].
  /// In that case the overflow bar will expand to fill the available
  /// width and it will layout its [children] in a column. The
  /// horizontal alignment of each child within that column is
  /// defined by this parameter and the [textDirection]. If the
  /// [textDirection] is [TextDirection.ltr] then each child will be
  /// aligned with the left edge of the available space for
  /// [OverflowBarAlignment.start], with the right edge of the
  /// available space for [OverflowBarAlignment.end]. Similarly, if the
  /// [textDirection] is [TextDirection.rtl] then each child will
  /// be aligned with the right edge of the available space for
  /// [OverflowBarAlignment.start], and with the left edge of the
  /// available space for [OverflowBarAlignment.end]. For
  /// [OverflowBarAlignment.center] each child is horizontally
  /// centered within the available space.
  ///
  /// Defaults to [OverflowBarAlignment.start].
  ///
  /// See also:
  ///
  ///  * [alignment], which defines the [children]'s horizontal layout
  ///    (according to the same rules as for [Row.mainAxisAlignment]) when
  ///    the children, separated by [spacing], fit within the available space.
  ///  * [overflowDirection], which defines the order that the
  ///    [OverflowBar]'s children appear in, if the horizontal layout
  ///    overflows.
  final OverflowBarAlignment overflowAlignment;

  /// Defines the order that the [children] appear in, if
  /// the horizontal layout overflows.
  ///
  /// This parameter is only used if the horizontal layout overflows, i.e.
  /// if there isn't enough horizontal room for the [children] and [spacing].
  ///
  /// If the children do not fit into a single row, then they
  /// are arranged in a column. The first child is at the top of the
  /// column if this property is set to [VerticalDirection.down], since it
  /// "starts" at the top and "ends" at the bottom. On the other hand,
  /// the first child will be at the bottom of the column if this
  /// property is set to [VerticalDirection.up], since it "starts" at the
  /// bottom and "ends" at the top.
  ///
  /// Defaults to [VerticalDirection.down].
  ///
  /// See also:
  ///
  ///  * [overflowAlignment], which defines the horizontal alignment
  ///    of the children within the vertical "overflow" layout.
  final VerticalDirection overflowDirection;

  /// Determines the order that the [children] appear in for the default
  /// horizontal layout, and the interpretation of
  /// [OverflowBarAlignment.start] and [OverflowBarAlignment.end] for
  /// the vertical overflow layout.
  ///
  /// For the default horizontal layout, if [textDirection] is
  /// [TextDirection.rtl] then the last child is laid out first. If
  /// [textDirection] is [TextDirection.ltr] then the first child is
  /// laid out first.
  ///
  /// If this parameter is null, then the value of
  /// `Directionality.of(context)` is used.
  ///
  /// See also:
  ///
  ///  * [overflowDirection], which defines the order that the
  ///    [OverflowBar]'s children appear in, if the horizontal layout
  ///    overflows.
  ///  * [Directionality], which defines the ambient directionality of
  ///    text and text-direction-sensitive render objects.
  final TextDirection? textDirection;

  /// {@macro flutter.material.Material.clipBehavior}
  ///
  /// Defaults to [Clip.none], and must not be null.
  final Clip clipBehavior;

  @override
  RenderObject createRenderObject(BuildContext context) {
    return _RenderOverflowBar(
      spacing: spacing,
      alignment: alignment,
      overflowSpacing: overflowSpacing,
      overflowAlignment: overflowAlignment,
      overflowDirection: overflowDirection,
      textDirection: textDirection ?? Directionality.of(context),
      clipBehavior: clipBehavior,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderObject renderObject) {
    (renderObject as _RenderOverflowBar)
      ..spacing = spacing
      ..alignment = alignment
      ..overflowSpacing = overflowSpacing
      ..overflowAlignment = overflowAlignment
      ..overflowDirection = overflowDirection
      ..textDirection = textDirection ?? Directionality.of(context)
      ..clipBehavior = clipBehavior;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('spacing', spacing, defaultValue: 0));
    properties.add(EnumProperty<MainAxisAlignment>('alignment', alignment, defaultValue: null));
    properties.add(DoubleProperty('overflowSpacing', overflowSpacing, defaultValue: 0));
    properties.add(EnumProperty<OverflowBarAlignment>('overflowAlignment', overflowAlignment, defaultValue: OverflowBarAlignment.start));
    properties.add(EnumProperty<VerticalDirection>('overflowDirection', overflowDirection, defaultValue: VerticalDirection.down));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
  }
}

class _OverflowBarParentData extends ContainerBoxParentData<RenderBox> { }

class _RenderOverflowBar extends RenderBox
    with ContainerRenderObjectMixin<RenderBox, _OverflowBarParentData>,
         RenderBoxContainerDefaultsMixin<RenderBox, _OverflowBarParentData> {
  _RenderOverflowBar({
    List<RenderBox>? children,
    double spacing = 0.0,
    MainAxisAlignment? alignment,
    double overflowSpacing = 0.0,
    OverflowBarAlignment overflowAlignment = OverflowBarAlignment.start,
    VerticalDirection overflowDirection = VerticalDirection.down,
    required TextDirection textDirection,
    Clip clipBehavior = Clip.none,
  }) : assert(spacing != null),
       assert(overflowSpacing != null),
       assert(overflowAlignment != null),
       assert(textDirection != null),
       assert(clipBehavior != null),
       _spacing = spacing,
       _alignment = alignment,
       _overflowSpacing = overflowSpacing,
       _overflowAlignment = overflowAlignment,
       _overflowDirection = overflowDirection,
       _textDirection = textDirection,
       _clipBehavior = clipBehavior {
    addAll(children);
  }

  double get spacing => _spacing;
  double _spacing;
  set spacing (double value) {
    assert(value != null);
    if (_spacing == value)
      return;
    _spacing = value;
    markNeedsLayout();
  }

  MainAxisAlignment? get alignment => _alignment;
  MainAxisAlignment? _alignment;
  set alignment (MainAxisAlignment? value) {
    if (_alignment == value)
      return;
    _alignment = value;
    markNeedsLayout();
  }

  double get overflowSpacing => _overflowSpacing;
  double _overflowSpacing;
  set overflowSpacing (double value) {
    assert(value != null);
    if (_overflowSpacing == value)
      return;
    _overflowSpacing = value;
    markNeedsLayout();
  }

  OverflowBarAlignment get overflowAlignment => _overflowAlignment;
  OverflowBarAlignment _overflowAlignment;
  set overflowAlignment (OverflowBarAlignment value) {
    assert(value != null);
    if (_overflowAlignment == value)
      return;
    _overflowAlignment = value;
    markNeedsLayout();
  }

  VerticalDirection get overflowDirection => _overflowDirection;
  VerticalDirection _overflowDirection;
  set overflowDirection (VerticalDirection value) {
    assert(value != null);
    if (_overflowDirection == value)
      return;
    _overflowDirection = value;
    markNeedsLayout();
  }

  TextDirection get textDirection => _textDirection;
  TextDirection _textDirection;
  set textDirection(TextDirection value) {
    if (_textDirection == value)
      return;
    _textDirection = value;
    markNeedsLayout();
  }

  Clip get clipBehavior => _clipBehavior;
  Clip _clipBehavior = Clip.none;
  set clipBehavior(Clip value) {
    assert(value != null);
    if (value == _clipBehavior)
      return;
    _clipBehavior = value;
    markNeedsPaint();
    markNeedsSemanticsUpdate();
  }

  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! _OverflowBarParentData)
      child.parentData = _OverflowBarParentData();
  }

  @override
  double computeMinIntrinsicHeight(double width) {
    RenderBox? child = firstChild;
    if (child == null)
      return 0;
    double barWidth = 0.0;
    while (child != null) {
      barWidth += child.getMinIntrinsicWidth(double.infinity);
      child = childAfter(child);
    }
    barWidth += spacing * (childCount - 1);

    double height = 0.0;
    if (barWidth > width) {
      child = firstChild;
      while (child != null) {
        height += child.getMinIntrinsicHeight(width);
        child = childAfter(child);
      }
      return height + overflowSpacing * (childCount - 1);
    } else {
      child = firstChild;
      while (child != null) {
        height = math.max(height, child.getMinIntrinsicHeight(width));
        child = childAfter(child);
      }
      return height;
    }
  }

  @override
  double computeMaxIntrinsicHeight(double width) {
    RenderBox? child = firstChild;
    if (child == null)
      return 0;
    double barWidth = 0.0;
    while (child != null) {
      barWidth += child.getMinIntrinsicWidth(double.infinity);
      child = childAfter(child);
    }
    barWidth += spacing * (childCount - 1);

    double height = 0.0;
    if (barWidth > width) {
      child = firstChild;
      while (child != null) {
        height += child.getMaxIntrinsicHeight(width);
        child = childAfter(child);
      }
      return height + overflowSpacing * (childCount - 1);
    } else {
      child = firstChild;
      while (child != null) {
        height = math.max(height, child.getMaxIntrinsicHeight(width));
        child = childAfter(child);
      }
      return height;
    }
  }

  @override
  double computeMinIntrinsicWidth(double height) {
    RenderBox? child = firstChild;
    if (child == null)
      return 0;
    double width = 0.0;
    while (child != null) {
      width += child.getMinIntrinsicWidth(double.infinity);
      child = childAfter(child);
    }
    return width + spacing * (childCount - 1);
  }

  @override
  double computeMaxIntrinsicWidth(double height) {
    RenderBox? child = firstChild;
    if (child == null)
      return 0;
    double width = 0.0;
    while (child != null) {
      width += child.getMaxIntrinsicWidth(double.infinity);
      child = childAfter(child);
    }
    return width + spacing * (childCount - 1);
  }

  @override
  double? computeDistanceToActualBaseline(TextBaseline baseline) {
    return defaultComputeDistanceToHighestActualBaseline(baseline);
  }

  @override
  Size computeDryLayout(BoxConstraints constraints) {
    RenderBox? child = firstChild;
    if (child == null) {
      return constraints.smallest;
    }
    final BoxConstraints childConstraints = constraints.loosen();
    double childrenWidth = 0.0;
    double maxChildHeight = 0.0;
    double y = 0.0;
    while (child != null) {
      final Size childSize = child.getDryLayout(childConstraints);
      childrenWidth += childSize.width;
      maxChildHeight = math.max(maxChildHeight, childSize.height);
      y += childSize.height + overflowSpacing;
      child = childAfter(child);
    }
    final double actualWidth = childrenWidth + spacing * (childCount - 1);
    if (actualWidth > constraints.maxWidth) {
      return constraints.constrain(Size(constraints.maxWidth, y - overflowSpacing));
    } else {
      final double overallWidth = alignment == null ? actualWidth : constraints.maxWidth;
      return constraints.constrain(Size(overallWidth, maxChildHeight));
    }
  }

  @override
  void performLayout() {
    RenderBox? child = firstChild;
    if (child == null) {
      size = constraints.smallest;
      return;
    }

    final BoxConstraints childConstraints = constraints.loosen();
    double childrenWidth = 0;
    double maxChildHeight = 0;
    double maxChildWidth = 0;

    while (child != null) {
      child.layout(childConstraints, parentUsesSize: true);
      childrenWidth += child.size.width;
      maxChildHeight = math.max(maxChildHeight, child.size.height);
      maxChildWidth = math.max(maxChildWidth, child.size.width);
      child = childAfter(child);
    }

    final bool rtl = textDirection == TextDirection.rtl;
    final double actualWidth = childrenWidth + spacing * (childCount - 1);

    if (actualWidth > constraints.maxWidth) {
      // Overflow vertical layout
      child = overflowDirection == VerticalDirection.down ? firstChild : lastChild;
      RenderBox? nextChild() => overflowDirection == VerticalDirection.down ? childAfter(child!) : childBefore(child!);
      double y = 0;
      while (child != null) {
        final _OverflowBarParentData childParentData = child.parentData! as _OverflowBarParentData;
        double x = 0;
        switch (overflowAlignment) {
          case OverflowBarAlignment.start:
            x = rtl ? constraints.maxWidth - child.size.width : 0;
            break;
          case OverflowBarAlignment.center:
            x = (constraints.maxWidth - child.size.width) / 2;
            break;
          case OverflowBarAlignment.end:
            x = rtl ? 0 : constraints.maxWidth - child.size.width;
            break;
        }
        assert(x != null);
        childParentData.offset = Offset(x, y);
        y += child.size.height + overflowSpacing;
        child = nextChild();
      }
      size = constraints.constrain(Size(constraints.maxWidth, y - overflowSpacing));
    } else {
      // Default horizontal layout
      child = firstChild;
      final double firstChildWidth = child!.size.width;
      final double overallWidth = alignment == null ? actualWidth : constraints.maxWidth;
      size = constraints.constrain(Size(overallWidth, maxChildHeight));

      late double x; // initial value: origin of the first child
      double layoutSpacing = spacing; // space between children
      switch (alignment) {
        case null:
          x = rtl ? size.width - firstChildWidth : 0;
          break;
        case MainAxisAlignment.start:
          x = rtl ? size.width - firstChildWidth : 0;
          break;
        case MainAxisAlignment.center:
          final double halfRemainingWidth = (size.width - actualWidth) / 2;
          x = rtl ? size.width - halfRemainingWidth - firstChildWidth : halfRemainingWidth;
          break;
        case MainAxisAlignment.end:
          x = rtl ? actualWidth - firstChildWidth : size.width - actualWidth;
          break;
        case MainAxisAlignment.spaceBetween:
          layoutSpacing = (size.width - childrenWidth) / (childCount - 1);
          x = rtl ? size.width - firstChildWidth : 0;
          break;
        case MainAxisAlignment.spaceAround:
          layoutSpacing = childCount > 0 ? (size.width - childrenWidth) / childCount : 0;
          x = rtl ? size.width - layoutSpacing / 2 - firstChildWidth : layoutSpacing / 2;
          break;
        case MainAxisAlignment.spaceEvenly:
          layoutSpacing = (size.width - childrenWidth) / (childCount + 1);
          x = rtl ? size.width - layoutSpacing - firstChildWidth : layoutSpacing;
          break;
      }

      while (child != null) {
        final _OverflowBarParentData childParentData = child.parentData! as _OverflowBarParentData;
        childParentData.offset = Offset(x, (maxChildHeight - child.size.height) / 2);
        // x is the horizontal origin of child. To advance x to the next child's
        // origin for LTR: add the width of the current child. To advance x to
        // the origin of the next child for RTL: subtract the width of the next
        // child (if there is one).
        if (!rtl) {
          x += child.size.width + layoutSpacing;
        }
        child = childAfter(child);
        if (rtl && child != null) {
          x -= child.size.width + layoutSpacing;
        }
      }
    }
  }

  @override
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
    return defaultHitTestChildren(result, position: position);
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    defaultPaint(context, offset);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('spacing', spacing, defaultValue: 0));
    properties.add(DoubleProperty('overflowSpacing', overflowSpacing, defaultValue: 0));
    properties.add(EnumProperty<OverflowBarAlignment>('overflowAlignment', overflowAlignment, defaultValue: OverflowBarAlignment.start));
    properties.add(EnumProperty<VerticalDirection>('overflowDirection', overflowDirection, defaultValue: VerticalDirection.down));
    properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
  }
}
