/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Float layout.
//!
//! See CSS 2.1 § 9.5.1: <https://www.w3.org/TR/CSS2/visuren.html#float-position>

use std::collections::VecDeque;
use std::fmt::Debug;
use std::mem;
use std::ops::Range;

use app_units::{Au, MAX_AU, MIN_AU};
use euclid::num::Zero;
use malloc_size_of_derive::MallocSizeOf;
use servo_arc::Arc;
use style::computed_values::float::T as FloatProperty;
use style::computed_values::position::T as Position;
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues;
use style::values::computed::Clear as StyleClear;

use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::{BoxFragment, CollapsedMargin};
use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
use crate::positioned::{PositioningContext, relative_adjustement};
use crate::style_ext::{DisplayInside, PaddingBorderMargin};
use crate::{ContainingBlock, PropagatedBoxTreeData};

/// A floating box.
#[derive(Debug, MallocSizeOf)]
pub(crate) struct FloatBox {
    /// The formatting context that makes up the content of this box.
    pub contents: IndependentFormattingContext,
}

/// `FloatContext` positions floats relative to the independent block formatting
/// context which contains the floating elements. The Fragment tree positions
/// elements relative to their containing blocks. This data structure is used to
/// help map between these two coordinate systems.
#[derive(Clone, Copy, Debug)]
pub struct ContainingBlockPositionInfo {
    /// The distance from the block start of the independent block formatting
    /// context that contains the floats and the block start of the current
    /// containing block, excluding uncollapsed block start margins. Note that
    /// this does not include uncollapsed block start margins because we don't
    /// know the value of collapsed margins until we lay out children.
    pub(crate) block_start: Au,
    /// Any uncollapsed block start margins that we have collected between the
    /// block start of the float containing independent block formatting context
    /// and this containing block, including for this containing block.
    pub(crate) block_start_margins_not_collapsed: CollapsedMargin,
    /// The distance from the inline start position of the float containing
    /// independent formatting context and the inline start of this containing
    /// block.
    pub inline_start: Au,
    /// The offset from the inline start position of the float containing
    /// independent formatting context to the inline end of this containing
    /// block.
    pub inline_end: Au,
}

impl ContainingBlockPositionInfo {
    pub fn new_with_inline_offsets(inline_start: Au, inline_end: Au) -> Self {
        Self {
            block_start: Au::zero(),
            block_start_margins_not_collapsed: CollapsedMargin::zero(),
            inline_start,
            inline_end,
        }
    }
}

/// This data strucure is used to try to place non-floating content among float content.
/// This is used primarily to place replaced content and independent formatting contexts
/// next to floats, as the specifcation dictates.
pub(crate) struct PlacementAmongFloats<'a> {
    /// The [FloatContext] to use for this placement.
    float_context: &'a FloatContext,
    /// The current bands we are considering for this placement.
    current_bands: VecDeque<FloatBand>,
    /// The next band, needed to know the height of the last band in current_bands.
    next_band: FloatBand,
    /// The size of the object to place.
    object_size: LogicalVec2<Au>,
    /// The minimum position in the block direction for the placement. Objects should not
    /// be placed before this point.
    ceiling: Au,
    /// The inline position where the object would be if there were no floats. The object
    /// can be placed after it due to floats, but not before it.
    min_inline_start: Au,
    /// The maximum inline position that the object can attain when avoiding floats.
    max_inline_end: Au,
}

impl<'a> PlacementAmongFloats<'a> {
    pub(crate) fn new(
        float_context: &'a FloatContext,
        ceiling: Au,
        object_size: LogicalVec2<Au>,
        pbm: &PaddingBorderMargin,
    ) -> Self {
        let mut ceiling_band = float_context.bands.find(ceiling).unwrap();
        let (current_bands, next_band) = if ceiling == MAX_AU {
            (VecDeque::new(), ceiling_band)
        } else {
            ceiling_band.top = ceiling;
            let current_bands = VecDeque::from([ceiling_band]);
            let next_band = float_context.bands.find_next(ceiling).unwrap();
            (current_bands, next_band)
        };
        let min_inline_start = float_context.containing_block_info.inline_start +
            pbm.margin.inline_start.auto_is(Au::zero);
        let max_inline_end = (float_context.containing_block_info.inline_end -
            pbm.margin.inline_end.auto_is(Au::zero))
        .max(min_inline_start + object_size.inline);
        PlacementAmongFloats {
            float_context,
            current_bands,
            next_band,
            object_size,
            ceiling,
            min_inline_start,
            max_inline_end,
        }
    }

    /// The top of the bands under consideration. This is initially the ceiling provided
    /// during creation of this [`PlacementAmongFloats`], but may be larger if the top
    /// band is discarded.
    fn top_of_bands(&self) -> Option<Au> {
        self.current_bands.front().map(|band| band.top)
    }

    /// The height of the bands under consideration.
    fn current_bands_height(&self) -> Au {
        if self.next_band.top == MAX_AU {
            // Treat MAX_AU as infinity.
            MAX_AU
        } else {
            let top = self
                .top_of_bands()
                .expect("Should have bands before reaching the end");
            self.next_band.top - top
        }
    }

    /// Add a single band to the bands under consideration and calculate the new
    /// [`PlacementAmongFloats::next_band`].
    fn add_one_band(&mut self) {
        assert!(self.next_band.top != MAX_AU);
        self.current_bands.push_back(self.next_band);
        self.next_band = self
            .float_context
            .bands
            .find_next(self.next_band.top)
            .unwrap();
    }

    /// Adds bands to the set of bands under consideration until their block size is at
    /// least large enough to contain the block size of the object being placed.
    fn accumulate_enough_bands_for_block_size(&mut self) {
        while self.current_bands_height() < self.object_size.block {
            self.add_one_band();
        }
    }

    /// Find the start and end of the inline space provided by the current set of bands
    /// under consideration.
    fn calculate_inline_start_and_end(&self) -> (Au, Au) {
        let mut max_inline_start = self.min_inline_start;
        let mut min_inline_end = self.max_inline_end;
        for band in self.current_bands.iter() {
            if let Some(inline_start) = band.inline_start {
                max_inline_start.max_assign(inline_start);
            }
            if let Some(inline_end) = band.inline_end {
                min_inline_end.min_assign(inline_end);
            }
        }
        (max_inline_start, min_inline_end)
    }

    /// Find the total inline size provided by the current set of bands under consideration.
    fn calculate_viable_inline_size(&self) -> Au {
        let (inline_start, inline_end) = self.calculate_inline_start_and_end();
        inline_end - inline_start
    }

    fn try_place_once(&mut self) -> Option<LogicalRect<Au>> {
        assert!(!self.current_bands.is_empty());
        self.accumulate_enough_bands_for_block_size();
        let (inline_start, inline_end) = self.calculate_inline_start_and_end();
        let available_inline_size = inline_end - inline_start;
        if available_inline_size < self.object_size.inline {
            return None;
        }
        Some(LogicalRect {
            start_corner: LogicalVec2 {
                inline: inline_start,
                block: self.top_of_bands().unwrap(),
            },
            size: LogicalVec2 {
                inline: available_inline_size,
                block: self.current_bands_height(),
            },
        })
    }

    /// Checks if we either have bands or we have gone past all of them.
    /// This is an invariant that should hold, otherwise we are in a broken state.
    fn has_bands_or_at_end(&self) -> bool {
        !self.current_bands.is_empty() || self.next_band.top == MAX_AU
    }

    fn pop_front_band_ensuring_has_bands_or_at_end(&mut self) {
        self.current_bands.pop_front();
        if !self.has_bands_or_at_end() {
            self.add_one_band();
        }
    }

    /// Run the placement algorithm for this [PlacementAmongFloats].
    pub(crate) fn place(&mut self) -> LogicalRect<Au> {
        debug_assert!(self.has_bands_or_at_end());
        while !self.current_bands.is_empty() {
            if let Some(result) = self.try_place_once() {
                return result;
            }
            self.pop_front_band_ensuring_has_bands_or_at_end();
        }
        debug_assert!(self.has_bands_or_at_end());

        // We could not fit the object in among the floats, so we place it as if it
        // cleared all floats.
        LogicalRect {
            start_corner: LogicalVec2 {
                inline: self.min_inline_start,
                block: self
                    .ceiling
                    .max(self.float_context.clear_inline_start_position)
                    .max(self.float_context.clear_inline_end_position),
            },
            size: LogicalVec2 {
                inline: self.max_inline_end - self.min_inline_start,
                block: MAX_AU,
            },
        }
    }

    /// After placing an object with `height: auto` (and using the minimum inline and
    /// block size as the object size) and then laying it out, try to fit the object into
    /// the current set of bands, given block size after layout and the available inline
    /// space from the original placement. This will return true if the object fits at the
    /// original placement location or false if the placement and layout must be run again
    /// (with this [PlacementAmongFloats]).
    pub(crate) fn try_to_expand_for_auto_block_size(
        &mut self,
        block_size_after_layout: Au,
        size_from_placement: &LogicalVec2<Au>,
    ) -> bool {
        debug_assert!(self.has_bands_or_at_end());
        debug_assert_eq!(size_from_placement.block, self.current_bands_height());
        debug_assert_eq!(
            size_from_placement.inline,
            self.calculate_viable_inline_size()
        );

        // If the object after layout fits into the originally calculated placement, then
        // it fits without any more work.
        if block_size_after_layout <= size_from_placement.block {
            return true;
        }

        // Keep searching until we have found an area with enough height
        // to contain the block after layout.
        let old_num_bands = self.current_bands.len();
        assert!(old_num_bands > 0);
        while self.current_bands_height() < block_size_after_layout {
            self.add_one_band();

            // If the new inline size is narrower, we must stop and run layout again.
            // Normally, a narrower block size means a bigger height, but in some
            // circumstances, such as when aspect ratio is used a narrower inline size
            // can counter-interuitively lead to a smaller block size after layout!
            let available_inline_size = self.calculate_viable_inline_size();
            if available_inline_size < size_from_placement.inline {
                // If the inline size becomes smaller than the minimum inline size, then
                // the current set of bands will never work and we must try removing the
                // first and searching starting from the second.
                if available_inline_size < self.object_size.inline {
                    self.next_band = self.current_bands[old_num_bands];
                    self.current_bands.truncate(old_num_bands);
                    self.pop_front_band_ensuring_has_bands_or_at_end();
                }
                return false;
            }
        }
        true
    }
}

/// Data kept during layout about the floats in a given block formatting context.
///
/// This is a persistent data structure. Each float has its own private copy of the float context,
/// although such copies may share portions of the `bands` tree.
#[derive(Clone, Debug)]
pub struct FloatContext {
    /// A persistent AA tree of float bands.
    ///
    /// This tree is immutable; modification operations return the new tree, which may share nodes
    /// with previous versions of the tree.
    pub bands: FloatBandTree,
    /// The block-direction "ceiling" defined by the placement of other floated content of
    /// this FloatContext. No new floats can be placed at a lower block start than this value.
    pub ceiling_from_floats: Au,
    /// The block-direction "ceiling" defined by the placement of non-floated content that
    /// precedes floated content in the document. Note that this may actually decrease as
    /// content is laid out in the case that content overflows its container.
    pub ceiling_from_non_floats: Au,
    /// Details about the position of the containing block relative to the
    /// independent block formatting context that contains all of the floats
    /// this `FloatContext` positions.
    pub containing_block_info: ContainingBlockPositionInfo,
    /// The (logically) lowest margin edge of the last inline-start float.
    pub clear_inline_start_position: Au,
    /// The (logically) lowest margin edge of the last inline-end float.
    pub clear_inline_end_position: Au,
}

impl FloatContext {
    /// Returns a new float context representing a containing block with the given content
    /// inline-size.
    pub fn new(max_inline_size: Au) -> Self {
        let mut bands = FloatBandTree::new();
        bands = bands.insert(FloatBand {
            top: MIN_AU,
            inline_start: None,
            inline_end: None,
        });
        bands = bands.insert(FloatBand {
            top: MAX_AU,
            inline_start: None,
            inline_end: None,
        });
        FloatContext {
            bands,
            ceiling_from_floats: Au::zero(),
            ceiling_from_non_floats: Au::zero(),
            containing_block_info: ContainingBlockPositionInfo::new_with_inline_offsets(
                Au::zero(),
                max_inline_size,
            ),
            clear_inline_start_position: Au::zero(),
            clear_inline_end_position: Au::zero(),
        }
    }

    /// (Logically) lowers the ceiling to at least `new_ceiling` units.
    ///
    /// If the ceiling is already logically lower (i.e. larger) than this, does nothing.
    pub fn set_ceiling_from_non_floats(&mut self, new_ceiling: Au) {
        self.ceiling_from_non_floats = new_ceiling;
    }

    /// The "ceiling" used for float placement. This is the minimum block position value
    /// that should be used for placing any new float.
    fn ceiling(&mut self) -> Au {
        self.ceiling_from_floats.max(self.ceiling_from_non_floats)
    }

    /// Determines where a float with the given placement would go, but leaves the float context
    /// unmodified. Returns the start corner of its margin box.
    ///
    /// This should be used for placing inline elements and block formatting contexts so that they
    /// don't collide with floats.
    pub(crate) fn place_object(&self, object: &PlacementInfo, ceiling: Au) -> LogicalVec2<Au> {
        let ceiling = match object.clear {
            Clear::None => ceiling,
            Clear::InlineStart => ceiling.max(self.clear_inline_start_position),
            Clear::InlineEnd => ceiling.max(self.clear_inline_end_position),
            Clear::Both => ceiling
                .max(self.clear_inline_start_position)
                .max(self.clear_inline_end_position),
        };

        // Find the first band this float fits in.
        let mut first_band = self.bands.find(ceiling).unwrap();
        while !first_band.object_fits(object, &self.containing_block_info) {
            let next_band = self.bands.find_next(first_band.top).unwrap();
            if next_band.top == MAX_AU {
                break;
            }
            first_band = next_band;
        }

        // The object fits perfectly here. Place it.
        match object.side {
            FloatSide::InlineStart => {
                let inline_start_object_edge = match first_band.inline_start {
                    Some(inline_start) => inline_start.max(self.containing_block_info.inline_start),
                    None => self.containing_block_info.inline_start,
                };
                LogicalVec2 {
                    inline: inline_start_object_edge,
                    block: first_band.top.max(ceiling),
                }
            },
            FloatSide::InlineEnd => {
                let inline_end_object_edge = match first_band.inline_end {
                    Some(inline_end) => inline_end.min(self.containing_block_info.inline_end),
                    None => self.containing_block_info.inline_end,
                };
                LogicalVec2 {
                    inline: inline_end_object_edge - object.size.inline,
                    block: first_band.top.max(ceiling),
                }
            },
        }
    }

    /// Places a new float and adds it to the list. Returns the start corner of its margin box.
    pub fn add_float(&mut self, new_float: &PlacementInfo) -> LogicalVec2<Au> {
        // Place the float.
        let ceiling = self.ceiling();
        let new_float_origin = self.place_object(new_float, ceiling);
        let new_float_extent = match new_float.side {
            FloatSide::InlineStart => new_float_origin.inline + new_float.size.inline,
            FloatSide::InlineEnd => new_float_origin.inline,
        };

        let new_float_rect = LogicalRect {
            start_corner: new_float_origin,
            // If this float has a negative margin, we should only consider its non-negative
            // block size contribution when determing where to place it. When the margin is
            // so negative that it's placed completely above the current float ceiling, then
            // we should position it as if it had zero block size.
            size: LogicalVec2 {
                inline: new_float.size.inline.max(Au::zero()),
                block: new_float.size.block.max(Au::zero()),
            },
        };

        // Update clear.
        match new_float.side {
            FloatSide::InlineStart => {
                self.clear_inline_start_position
                    .max_assign(new_float_rect.max_block_position());
            },
            FloatSide::InlineEnd => {
                self.clear_inline_end_position
                    .max_assign(new_float_rect.max_block_position());
            },
        }

        // Split the first band if necessary.
        let mut first_band = self.bands.find(new_float_rect.start_corner.block).unwrap();
        first_band.top = new_float_rect.start_corner.block;
        self.bands = self.bands.insert(first_band);

        // Split the last band if necessary.
        let mut last_band = self
            .bands
            .find(new_float_rect.max_block_position())
            .unwrap();
        last_band.top = new_float_rect.max_block_position();
        self.bands = self.bands.insert(last_band);

        // Update all bands that contain this float to reflect the new available size.
        let block_range = new_float_rect.start_corner.block..new_float_rect.max_block_position();
        self.bands = self
            .bands
            .set_range(&block_range, new_float.side, new_float_extent);

        // CSS 2.1 § 9.5.1 rule 6: The outer top of a floating box may not be higher than the outer
        // top of any block or floated box generated by an element earlier in the source document.
        self.ceiling_from_floats
            .max_assign(new_float_rect.start_corner.block);

        new_float_rect.start_corner
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Clear {
    None,
    InlineStart,
    InlineEnd,
    Both,
}

impl Clear {
    pub(crate) fn from_style_and_container_writing_mode(
        style: &ComputedValues,
        container_writing_mode: WritingMode,
    ) -> Self {
        match style.get_box().clear {
            StyleClear::None => Self::None,
            StyleClear::Both => Self::Both,
            StyleClear::InlineStart => Self::InlineStart,
            StyleClear::InlineEnd => Self::InlineEnd,
            StyleClear::Left if container_writing_mode.is_bidi_ltr() => Self::InlineStart,
            StyleClear::Left => Self::InlineEnd,
            StyleClear::Right if container_writing_mode.is_bidi_ltr() => Self::InlineEnd,
            StyleClear::Right => Self::InlineStart,
        }
    }
}

/// Information needed to place a float so that it doesn't collide with existing floats.
#[derive(Clone, Debug)]
pub struct PlacementInfo {
    /// The *margin* box size of the float.
    pub size: LogicalVec2<Au>,
    /// Which side of the containing block the float is aligned to.
    pub side: FloatSide,
    /// Which side or sides to clear existing floats on.
    pub clear: Clear,
}

/// Whether the float is aligned to the inline-start or inline-end side of its containing block.
///
/// See CSS 2.1 § 9.5.1: <https://www.w3.org/TR/CSS2/visuren.html#float-position>
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum FloatSide {
    InlineStart,
    InlineEnd,
}

/// Internal data structure that describes a nonoverlapping vertical region in which floats may be placed.
/// Floats must go between "inline-start edge + `inline_start`" and "inline-end edge - `inline_end`".
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct FloatBand {
    /// The logical vertical position of the top of this band.
    pub top: Au,
    /// The distance from the inline-start edge of the block formatting context to the first legal
    /// (logically) horizontal position where floats may be placed. If `None`, there are no floats
    /// to the inline-start; distinguishing between the cases of "a zero-width float is present" and
    /// "no floats at all are present" is necessary to, for example, clear past zero-width floats.
    pub inline_start: Option<Au>,
    /// The distance from the *inline-start* edge of the block formatting context to the last legal
    /// (logically) horizontal position where floats may be placed. If `None`, there are no floats
    /// to the inline-end; distinguishing between the cases of "a zero-width float is present" and
    /// "no floats at all are present" is necessary to, for example, clear past zero-width floats.
    pub inline_end: Option<Au>,
}

impl FloatSide {
    pub(crate) fn from_style_and_container_writing_mode(
        style: &ComputedValues,
        container_writing_mode: WritingMode,
    ) -> Option<FloatSide> {
        Some(match style.get_box().float {
            FloatProperty::None => return None,
            FloatProperty::InlineStart => Self::InlineStart,
            FloatProperty::InlineEnd => Self::InlineEnd,
            FloatProperty::Left if container_writing_mode.is_bidi_ltr() => Self::InlineStart,
            FloatProperty::Left => Self::InlineEnd,
            FloatProperty::Right if container_writing_mode.is_bidi_ltr() => Self::InlineEnd,
            FloatProperty::Right => Self::InlineStart,
        })
    }
}

impl FloatBand {
    /// Determines whether an object fits in a band. Returns true if the object fits.
    fn object_fits(&self, object: &PlacementInfo, walls: &ContainingBlockPositionInfo) -> bool {
        match object.side {
            FloatSide::InlineStart => {
                // Compute a candidate inline-start position for the object.
                let candidate_inline_start = match self.inline_start {
                    None => walls.inline_start,
                    Some(inline_start) => inline_start.max(walls.inline_start),
                };

                // If this band has an existing inline-start float in it, then make sure that the object
                // doesn't stick out past the inline-end edge (rule 7).
                if self.inline_start.is_some() &&
                    candidate_inline_start + object.size.inline > walls.inline_end
                {
                    return false;
                }

                // If this band has an existing inline-end float in it, make sure we don't collide with
                // it (rule 3).
                match self.inline_end {
                    None => true,
                    Some(inline_end) => object.size.inline <= inline_end - candidate_inline_start,
                }
            },

            FloatSide::InlineEnd => {
                // Compute a candidate inline-end position for the object.
                let candidate_inline_end = match self.inline_end {
                    None => walls.inline_end,
                    Some(inline_end) => inline_end.min(walls.inline_end),
                };

                // If this band has an existing inline-end float in it, then make sure that the new
                // object doesn't stick out past the inline-start edge (rule 7).
                if self.inline_end.is_some() &&
                    candidate_inline_end - object.size.inline < walls.inline_start
                {
                    return false;
                }

                // If this band has an existing inline-start float in it, make sure we don't collide with
                // it (rule 3).
                match self.inline_start {
                    None => true,
                    Some(inline_start) => object.size.inline <= candidate_inline_end - inline_start,
                }
            },
        }
    }
}

// Float band storage

/// A persistent AA tree for float band storage.
///
/// Bands here are nonoverlapping, and there is guaranteed to be a band at block-position 0 and
/// another band at block-position infinity.
///
/// AA trees were chosen for simplicity.
///
/// See: <https://en.wikipedia.org/wiki/AA_tree>
///      <https://arxiv.org/pdf/1412.4882.pdf>
#[derive(Clone, Debug)]
pub struct FloatBandTree {
    pub root: FloatBandLink,
}

/// A single edge (or lack thereof) in the float band tree.
#[derive(Clone, Debug)]
pub struct FloatBandLink(pub Option<Arc<FloatBandNode>>);

/// A single node in the float band tree.
#[derive(Clone, Debug)]
pub struct FloatBandNode {
    /// The actual band.
    pub band: FloatBand,
    /// The left child.
    pub left: FloatBandLink,
    /// The right child.
    pub right: FloatBandLink,
    /// The level, which increases as you go up the tree.
    ///
    /// This value is needed for tree balancing.
    pub level: i32,
}

impl FloatBandTree {
    /// Creates a new float band tree.
    pub fn new() -> FloatBandTree {
        FloatBandTree {
            root: FloatBandLink(None),
        }
    }

    /// Returns the first band whose top is less than or equal to the given `block_position`.
    pub fn find(&self, block_position: Au) -> Option<FloatBand> {
        self.root.find(block_position)
    }

    /// Returns the first band whose top is strictly greater than to the given `block_position`.
    pub fn find_next(&self, block_position: Au) -> Option<FloatBand> {
        self.root.find_next(block_position)
    }

    /// Sets the side values of all bands within the given half-open range to be at least
    /// `new_value`.
    #[must_use]
    pub fn set_range(&self, range: &Range<Au>, side: FloatSide, new_value: Au) -> FloatBandTree {
        FloatBandTree {
            root: FloatBandLink(
                self.root
                    .0
                    .as_ref()
                    .map(|root| root.set_range(range, side, new_value)),
            ),
        }
    }

    /// Inserts a new band into the tree. If the band has the same level as a pre-existing one,
    /// replaces the existing band with the new one.
    #[must_use]
    pub fn insert(&self, band: FloatBand) -> FloatBandTree {
        FloatBandTree {
            root: self.root.insert(band),
        }
    }
}

impl Default for FloatBandTree {
    fn default() -> Self {
        Self::new()
    }
}

impl FloatBandNode {
    fn new(band: FloatBand) -> FloatBandNode {
        FloatBandNode {
            band,
            left: FloatBandLink(None),
            right: FloatBandLink(None),
            level: 1,
        }
    }

    /// Sets the side values of all bands within the given half-open range to be at least
    /// `new_value`.
    fn set_range(&self, range: &Range<Au>, side: FloatSide, new_value: Au) -> Arc<FloatBandNode> {
        let mut new_band = self.band;
        if self.band.top >= range.start && self.band.top < range.end {
            match side {
                FloatSide::InlineStart => {
                    new_band.inline_start = match new_band.inline_start {
                        Some(old_value) => Some(std::cmp::max(old_value, new_value)),
                        None => Some(new_value),
                    };
                },
                FloatSide::InlineEnd => {
                    new_band.inline_end = match new_band.inline_end {
                        Some(old_value) => Some(std::cmp::min(old_value, new_value)),
                        None => Some(new_value),
                    };
                },
            }
        }

        let new_left = match self.left.0 {
            None => FloatBandLink(None),
            Some(ref old_left) if range.start < new_band.top => {
                FloatBandLink(Some(old_left.set_range(range, side, new_value)))
            },
            Some(ref old_left) => FloatBandLink(Some((*old_left).clone())),
        };

        let new_right = match self.right.0 {
            None => FloatBandLink(None),
            Some(ref old_right) if range.end > new_band.top => {
                FloatBandLink(Some(old_right.set_range(range, side, new_value)))
            },
            Some(ref old_right) => FloatBandLink(Some((*old_right).clone())),
        };

        Arc::new(FloatBandNode {
            band: new_band,
            left: new_left,
            right: new_right,
            level: self.level,
        })
    }
}

impl FloatBandLink {
    /// Returns the first band whose top is less than or equal to the given `block_position`.
    fn find(&self, block_position: Au) -> Option<FloatBand> {
        let this = match self.0 {
            None => return None,
            Some(ref node) => node,
        };

        if block_position < this.band.top {
            return this.left.find(block_position);
        }

        // It's somewhere in this subtree, but we aren't sure whether it's here or in the right
        // subtree.
        if let Some(band) = this.right.find(block_position) {
            return Some(band);
        }

        Some(this.band)
    }

    /// Returns the first band whose top is strictly greater than the given `block_position`.
    fn find_next(&self, block_position: Au) -> Option<FloatBand> {
        let this = match self.0 {
            None => return None,
            Some(ref node) => node,
        };

        if block_position >= this.band.top {
            return this.right.find_next(block_position);
        }

        // It's somewhere in this subtree, but we aren't sure whether it's here or in the left
        // subtree.
        if let Some(band) = this.left.find_next(block_position) {
            return Some(band);
        }

        Some(this.band)
    }

    /// Inserts a new band into the tree. If the band has the same level as a pre-existing one,
    /// replaces the existing band with the new one.
    fn insert(&self, band: FloatBand) -> FloatBandLink {
        let mut this = match self.0 {
            None => return FloatBandLink(Some(Arc::new(FloatBandNode::new(band)))),
            Some(ref this) => (**this).clone(),
        };

        if band.top < this.band.top {
            this.left = this.left.insert(band);
            return FloatBandLink(Some(Arc::new(this))).skew().split();
        }
        if band.top > this.band.top {
            this.right = this.right.insert(band);
            return FloatBandLink(Some(Arc::new(this))).skew().split();
        }

        this.band = band;
        FloatBandLink(Some(Arc::new(this)))
    }

    /// Corrects tree balance:
    ///```text
    ///         T          L
    ///        / \        / \
    ///       L   R  →   A   T      if level(T) = level(L)
    ///      / \            / \
    ///     A   B          B   R
    /// ```
    fn skew(&self) -> FloatBandLink {
        if let Some(ref this) = self.0 {
            if let Some(ref left) = this.left.0 {
                if this.level == left.level {
                    return FloatBandLink(Some(Arc::new(FloatBandNode {
                        level: this.level,
                        left: left.left.clone(),
                        band: left.band,
                        right: FloatBandLink(Some(Arc::new(FloatBandNode {
                            level: this.level,
                            left: left.right.clone(),
                            band: this.band,
                            right: this.right.clone(),
                        }))),
                    })));
                }
            }
        }

        (*self).clone()
    }

    /// Corrects tree balance:
    ///```text
    ///         T            R
    ///        / \          / \
    ///       A   R   →    T   X    if level(T) = level(X)
    ///          / \      / \
    ///         B   X    A   B
    /// ```
    fn split(&self) -> FloatBandLink {
        if let Some(ref this) = self.0 {
            if let Some(ref right) = this.right.0 {
                if let Some(ref right_right) = right.right.0 {
                    if this.level == right_right.level {
                        return FloatBandLink(Some(Arc::new(FloatBandNode {
                            level: this.level + 1,
                            left: FloatBandLink(Some(Arc::new(FloatBandNode {
                                level: this.level,
                                left: this.left.clone(),
                                band: this.band,
                                right: right.left.clone(),
                            }))),
                            band: right.band,
                            right: right.right.clone(),
                        })));
                    }
                }
            }
        }

        (*self).clone()
    }
}

impl FloatBox {
    /// Creates a new float box.
    pub fn construct(
        context: &LayoutContext,
        info: &NodeAndStyleInfo<'_>,
        display_inside: DisplayInside,
        contents: Contents,
        propagated_data: PropagatedBoxTreeData,
    ) -> Self {
        Self {
            contents: IndependentFormattingContext::construct(
                context,
                info,
                display_inside,
                contents,
                propagated_data,
            ),
        }
    }

    /// Lay out this float box and its children. Note that the position will be relative to
    /// the float containing block formatting context. A later step adjusts the position
    /// to be relative to the containing block.
    pub fn layout(
        &self,
        layout_context: &LayoutContext,
        positioning_context: &mut PositioningContext,
        containing_block: &ContainingBlock,
    ) -> BoxFragment {
        positioning_context.layout_maybe_position_relative_fragment(
            layout_context,
            containing_block,
            &self.contents.base,
            |positioning_context| {
                self.contents
                    .layout_float_or_atomic_inline(
                        layout_context,
                        positioning_context,
                        containing_block,
                    )
                    .fragment
            },
        )
    }
}

/// Layout state that we maintain when doing sequential traversals of the box tree in document
/// order.
///
/// This data is only needed for float placement and float interaction, and as such is only present
/// if the current block formatting context contains floats.
///
/// All coordinates here are relative to the start of the nearest ancestor block formatting context.
///
/// This structure is expected to be cheap to clone, in order to allow for "snapshots" that enable
/// restarting layout at any point in the tree.
#[derive(Clone)]
pub(crate) struct SequentialLayoutState {
    /// Holds all floats in this block formatting context.
    pub(crate) floats: FloatContext,
    /// The (logically) bottom border edge or top padding edge of the last in-flow block. Floats
    /// cannot be placed above this line.
    ///
    /// This is often, but not always, the same as the float ceiling. The float ceiling can be lower
    /// than this value because this value is calculated based on in-flow boxes only, while
    /// out-of-flow floats can affect the ceiling as well (see CSS 2.1 § 9.5.1 rule 6).
    pub(crate) bfc_relative_block_position: Au,
    /// Any collapsible margins that we've encountered after `bfc_relative_block_position`.
    pub(crate) current_margin: CollapsedMargin,
}

impl SequentialLayoutState {
    /// Creates a new empty `SequentialLayoutState`.
    pub(crate) fn new(max_inline_size: Au) -> SequentialLayoutState {
        SequentialLayoutState {
            floats: FloatContext::new(max_inline_size),
            current_margin: CollapsedMargin::zero(),
            bfc_relative_block_position: Au::zero(),
        }
    }

    /// Moves the current block position (logically) down by `block_distance`. This may be
    /// a negative advancement in the case that that block content overflows its
    /// container, when the container is adjusting the block position of the
    /// [`SequentialLayoutState`] after processing its overflowing content.
    ///
    /// Floats may not be placed higher than the current block position.
    pub(crate) fn advance_block_position(&mut self, block_distance: Au) {
        self.bfc_relative_block_position += block_distance;
        self.floats
            .set_ceiling_from_non_floats(self.bfc_relative_block_position);
    }

    /// Replace the entire [ContainingBlockPositionInfo] data structure stored
    /// by this [SequentialLayoutState]. Return the old data structure.
    pub(crate) fn replace_containing_block_position_info(
        &mut self,
        mut position_info: ContainingBlockPositionInfo,
    ) -> ContainingBlockPositionInfo {
        mem::swap(&mut position_info, &mut self.floats.containing_block_info);
        position_info
    }

    /// Return the current block position in the float containing block formatting
    /// context and any uncollapsed block margins.
    pub(crate) fn current_block_position_including_margins(&self) -> Au {
        self.bfc_relative_block_position + self.current_margin.solve()
    }

    /// Collapses margins, moving the block position down by the collapsed value of `current_margin`
    /// and resetting `current_margin` to zero.
    ///
    /// Call this method before laying out children when it is known that the start margin of the
    /// current fragment can't collapse with the margins of any of its children.
    pub(crate) fn collapse_margins(&mut self) {
        self.advance_block_position(self.current_margin.solve());
        self.current_margin = CollapsedMargin::zero();
    }

    /// Computes the position of the block-start border edge of an element
    /// with the provided `block_start_margin`, assuming no clearance.
    pub(crate) fn position_without_clearance(&self, block_start_margin: &CollapsedMargin) -> Au {
        // Adjoin `current_margin` and `block_start_margin` since there is no clearance.
        self.bfc_relative_block_position + self.current_margin.adjoin(block_start_margin).solve()
    }

    /// Computes the position of the block-start border edge of an element
    /// with the provided `block_start_margin`, assuming a clearance of 0px.
    pub(crate) fn position_with_zero_clearance(&self, block_start_margin: &CollapsedMargin) -> Au {
        // Clearance prevents `current_margin` and `block_start_margin` from being
        // adjoining, so we need to solve them separately and then sum.
        self.bfc_relative_block_position + self.current_margin.solve() + block_start_margin.solve()
    }

    /// Returns the block-end outer edge of the lowest float that is to be cleared (if any)
    /// by an element with the provided `clear` and `block_start_margin`.
    pub(crate) fn calculate_clear_position(
        &self,
        clear: Clear,
        block_start_margin: &CollapsedMargin,
    ) -> Option<Au> {
        if clear == Clear::None {
            return None;
        }

        // Calculate the hypothetical position where the element's top border edge
        // would have been if the element's `clear` property had been `none`.
        let hypothetical_block_position = self.position_without_clearance(block_start_margin);

        // Check if the hypothetical position is past the relevant floats,
        // in that case we don't need to add clearance.
        let clear_position = match clear {
            Clear::None => unreachable!(),
            Clear::InlineStart => self.floats.clear_inline_start_position,
            Clear::InlineEnd => self.floats.clear_inline_end_position,
            Clear::Both => self
                .floats
                .clear_inline_start_position
                .max(self.floats.clear_inline_end_position),
        };
        if hypothetical_block_position >= clear_position {
            None
        } else {
            Some(clear_position)
        }
    }

    /// Returns the amount of clearance (if any) that a block with the given `clear` value
    /// needs to have at `current_block_position_including_margins()`.
    /// `block_start_margin` is the top margin of the block, after collapsing (if possible)
    /// with the margin of its contents. This must not be included in `current_margin`,
    /// since adding clearance will prevent `current_margin` and `block_start_margin`
    /// from collapsing together.
    ///
    /// <https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#flow-control>
    pub(crate) fn calculate_clearance(
        &self,
        clear: Clear,
        block_start_margin: &CollapsedMargin,
    ) -> Option<Au> {
        self.calculate_clear_position(clear, block_start_margin)
            .map(|offset| offset - self.position_with_zero_clearance(block_start_margin))
    }

    /// Adds a new adjoining margin.
    pub(crate) fn adjoin_assign(&mut self, margin: &CollapsedMargin) {
        self.current_margin.adjoin_assign(margin)
    }

    /// Get the offset of the current containing block and any uncollapsed margins.
    pub(crate) fn current_containing_block_offset(&self) -> Au {
        self.floats.containing_block_info.block_start +
            self.floats
                .containing_block_info
                .block_start_margins_not_collapsed
                .solve()
    }

    /// This function places a Fragment that has been created for a FloatBox.
    pub(crate) fn place_float_fragment(
        &mut self,
        box_fragment: &mut BoxFragment,
        containing_block: &ContainingBlock,
        margins_collapsing_with_parent_containing_block: CollapsedMargin,
        block_offset_from_containing_block_top: Au,
    ) {
        let block_start_of_containing_block_in_bfc = self.floats.containing_block_info.block_start +
            self.floats
                .containing_block_info
                .block_start_margins_not_collapsed
                .adjoin(&margins_collapsing_with_parent_containing_block)
                .solve();

        self.floats.set_ceiling_from_non_floats(
            block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top,
        );

        let container_writing_mode = containing_block.style.writing_mode;
        let logical_float_size = box_fragment
            .content_rect
            .size
            .to_logical(container_writing_mode);
        let pbm_sums = box_fragment
            .padding_border_margin()
            .to_logical(container_writing_mode);
        let margin_box_start_corner = self.floats.add_float(&PlacementInfo {
            size: logical_float_size + pbm_sums.sum(),
            side: FloatSide::from_style_and_container_writing_mode(
                &box_fragment.style,
                container_writing_mode,
            )
            .expect("Float box wasn't floated!"),
            clear: Clear::from_style_and_container_writing_mode(
                &box_fragment.style,
                container_writing_mode,
            ),
        });

        // Re-calculate relative adjustment so that it is not lost when the BoxFragment's
        // `content_rect` is overwritten below.
        let relative_offset = match box_fragment.style.clone_position() {
            Position::Relative => relative_adjustement(&box_fragment.style, containing_block),
            _ => LogicalVec2::zero(),
        };

        // This is the position of the float in the float-containing block formatting context. We add the
        // existing start corner here because we may have already gotten some relative positioning offset.
        let new_position_in_bfc =
            margin_box_start_corner + pbm_sums.start_offset() + relative_offset;

        // This is the position of the float relative to the containing block start.
        let new_position_in_containing_block = LogicalVec2 {
            inline: new_position_in_bfc.inline - self.floats.containing_block_info.inline_start,
            block: new_position_in_bfc.block - block_start_of_containing_block_in_bfc,
        };

        box_fragment.content_rect = LogicalRect {
            start_corner: new_position_in_containing_block,
            size: box_fragment
                .content_rect
                .size
                .to_logical(container_writing_mode),
        }
        .as_physical(Some(containing_block));
    }
}
