///|
/// Read the first-image dimensions from a Windows ICO or CUR container without
/// decoding any bitmap data. The width and height are stored as single bytes in
/// the first directory entry, where 0 means 256 pixels.

///|
pub fn ico_dimensions(bytes : Bytes) -> (Int32, Int32)? {
  if bytes.length() < 22 {
    return None
  }
  if read_little_endian_u16(bytes, 0) != 0 {
    return None
  }
  let image_type = read_little_endian_u16(bytes, 2)
  if image_type != 1 && image_type != 2 {
    return None
  }
  let entry_count = read_little_endian_u16(bytes, 4)
  if entry_count == 0 {
    return None
  }
  let width = bytes[6].to_int()
  let height = bytes[7].to_int()
  let resolved_width = if width == 0 { 256 } else { width }
  let resolved_height = if height == 0 { 256 } else { height }
  if resolved_width > 0 && resolved_height > 0 {
    Some((resolved_width, resolved_height))
  } else {
    None
  }
}

///|
async fn read_ico_dimensions(path : String, size : Int64) -> (Int32, Int32)? {
  if size < 22L {
    return None
  }
  let file = @fs.open(path, mode=@fs.ReadOnly)
  defer file.close()
  let header = file.read_exactly(22)
  ico_dimensions(header)
}

///|
test "reads ICO and CUR first-entry dimensions including the 256 case" {
  // reserved=0, type=1(icon), count=1, width=16, height=16
  let icon : Bytes = b"\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  assert_true(ico_dimensions(icon) == Some((16, 16)))
  // width=0 means 256
  let large : Bytes = b"\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  assert_true(ico_dimensions(large) == Some((256, 256)))
  // type=2 cursor
  let cursor : Bytes = b"\x00\x00\x02\x00\x01\x00\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  assert_true(ico_dimensions(cursor) == Some((32, 32)))
}

///|
test "rejects malformed ICO/CUR headers" {
  assert_true(ico_dimensions(b"not an icon") is None)
  let bad_type : Bytes = b"\x00\x00\x03\x00\x01\x00\x10\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  assert_true(ico_dimensions(bad_type) is None)
  let zero_count : Bytes = b"\x00\x00\x01\x00\x00\x00\x10\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  assert_true(ico_dimensions(zero_count) is None)
  let short : Bytes = b"\x00\x00\x01\x00\x01"
  assert_true(ico_dimensions(short) is None)
}