// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
fn collapse_state_add(
  state : (Double, Double),
  margin : Double,
) -> (Double, Double) {
  let mut max_pos = state.0
  let mut min_neg = state.1
  if margin > 0.0 {
    if margin > max_pos {
      max_pos = margin
    } else {
      ()
    }
  } else if margin < 0.0 {
    if margin < min_neg {
      min_neg = margin
    } else {
      ()
    }
  } else {
    ()
  }
  (max_pos, min_neg)
}

///|
fn collapse_state_value(state : (Double, Double)) -> Double {
  state.0 + state.1
}

///|
fn collapse_state_from(margin : Double) -> (Double, Double) {
  collapse_state_add((0.0, 0.0), margin)
}

///|
fn collapse_state_merge(
  a : (Double, Double),
  b : (Double, Double),
) -> (Double, Double) {
  (if a.0 > b.0 { a.0 } else { b.0 }, if a.1 < b.1 { a.1 } else { b.1 })
}

///|
fn[C] has_in_flow_children(
  tree : ChicleTree[C],
  children : Array[NodeId],
) -> Bool raise ChicleError {
  for child_id in children {
    let child = match tree.nodes.get(child_id) {
      Some(c) => c
      None => raise InvalidNodeId(child_id)
    }
    match child.style.display {
      DisplayNone => ()
      _ =>
        match child.style.position {
          PosRelative => return true
          PosAbsolute => ()
        }
    }
  }
  false
}

///|
fn[C] can_collapse_through_child(
  tree : ChicleTree[C],
  child_id : NodeId,
  child : NodeData,
  child_size : Size[Double],
) -> Bool raise ChicleError {
  match child.style.display {
    DisplayBlock => ()
    _ => return false
  }
  if child_size.height != 0.0 {
    return false
  } else {
    ()
  }
  match tree.node_context_data[child_id] {
    Some(_) => return false
    None => ()
  }
  let overflow_visible = match
    (child.style.overflow.x, child.style.overflow.y) {
    (OverflowVisible, OverflowVisible) => true
    _ => false
  }
  if !overflow_visible {
    return false
  } else {
    ()
  }
  if has_in_flow_children(tree, tree.children[child_id]) {
    return false
  } else {
    ()
  }
  true
}