///|
/// Resource management for intrinsic-sized elements (images, etc.)
/// Allows external systems to resolve sizes asynchronously

///|
/// Opaque resource identifier for external reference
pub(all) struct ResourceId(Int) derive(Eq, Hash, Debug)

///|
pub impl Show for ResourceId with fn output(self, logger) {
  let ResourceId(id) = self
  logger.write_string("ResourceId(\{id})")
}

///|
/// State of an intrinsic resource
pub(all) enum IntrinsicState {
  /// Size resolved successfully
  Resolved(width~ : Double, height~ : Double)
  /// Size pending (using placeholder)
  Pending(placeholder_width~ : Double, placeholder_height~ : Double)
  /// Load failed
  Error
}

///|
/// HTML default placeholder size (per specification)
pub let default_placeholder_width : Double = 300.0

///|
pub let default_placeholder_height : Double = 150.0

///|
/// Error placeholder size (broken image icon)
pub let error_placeholder_width : Double = 24.0

///|
pub let error_placeholder_height : Double = 24.0

///|
/// Create a fixed MeasureFunc for intrinsic sizing
pub fn create_fixed_measure(
  width : Double,
  height : Double,
) -> @layout_types.MeasureFunc {
  {
    func: fn(
      _available_width,
      _available_height,
    ) -> @layout_types.IntrinsicSize {
      {
        min_width: width,
        max_width: width,
        min_height: height,
        max_height: height,
      }
    },
  }
}

///|
/// Resource registry - tracks pending resources and their associated nodes
pub struct ResourceRegistry {
  /// Counter for generating unique resource IDs
  mut next_id : Int
  /// Map from resource ID to node UIDs
  resource_nodes : Map[Int, Array[Int]]
  /// Set of pending resource IDs
  pending : @hashset.HashSet[Int]
}

///|
pub fn ResourceRegistry::new() -> ResourceRegistry {
  { next_id: 0, resource_nodes: {}, pending: @hashset.HashSet([]) }
}

///|
/// Generate a new unique resource ID
pub fn ResourceRegistry::next_resource_id(
  self : ResourceRegistry,
) -> ResourceId {
  let id = self.next_id
  self.next_id += 1
  ResourceId(id)
}

///|
/// Associate a node UID with a resource ID
pub fn ResourceRegistry::add_node(
  self : ResourceRegistry,
  rid : ResourceId,
  node_uid : Int,
) -> Unit {
  let ResourceId(id) = rid
  match self.resource_nodes.get(id) {
    Some(nodes) => nodes.push(node_uid)
    None => self.resource_nodes[id] = [node_uid]
  }
}

///|
/// Mark a resource as pending (not yet resolved)
pub fn ResourceRegistry::mark_pending(
  self : ResourceRegistry,
  rid : ResourceId,
) -> Unit {
  let ResourceId(id) = rid
  self.pending.add(id)
}

///|
/// Mark a resource as resolved (size known)
pub fn ResourceRegistry::mark_resolved(
  self : ResourceRegistry,
  rid : ResourceId,
) -> Unit {
  let ResourceId(id) = rid
  self.pending.remove(id)
}

///|
/// Check if a resource is still pending
pub fn ResourceRegistry::is_pending(
  self : ResourceRegistry,
  rid : ResourceId,
) -> Bool {
  let ResourceId(id) = rid
  self.pending.contains(id)
}

///|
/// Get all node UIDs associated with a resource
pub fn ResourceRegistry::get_nodes(
  self : ResourceRegistry,
  rid : ResourceId,
) -> Array[Int] {
  let ResourceId(id) = rid
  match self.resource_nodes.get(id) {
    Some(nodes) => nodes
    None => []
  }
}

///|
/// Get all pending resource IDs
pub fn ResourceRegistry::get_all_pending(
  self : ResourceRegistry,
) -> Array[ResourceId] {
  self.pending.iter().map(fn(id) { ResourceId(id) }).collect()
}