// Copyright 2026 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.

///|
priv struct SidGid {
  sid : Int
  gid : Int
}

let standard_encoding_to_sid : Array[Int] = [
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
    17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
    33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
    49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
    65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
    81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
    0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
    0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
  137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
    0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
]

let expert_charset_sid_to_gid : Array[SidGid] = [
    SidGid::{ sid: 1, gid: 1 },     SidGid::{ sid: 13, gid: 12 },   SidGid::{ sid: 14, gid: 13 },   SidGid::{ sid: 15, gid: 14 },
    SidGid::{ sid: 27, gid: 26 },   SidGid::{ sid: 28, gid: 27 },   SidGid::{ sid: 99, gid: 15 },   SidGid::{ sid: 109, gid: 46 },
    SidGid::{ sid: 110, gid: 47 },  SidGid::{ sid: 150, gid: 111 }, SidGid::{ sid: 155, gid: 101 }, SidGid::{ sid: 158, gid: 100 },
    SidGid::{ sid: 163, gid: 102 }, SidGid::{ sid: 164, gid: 112 }, SidGid::{ sid: 169, gid: 113 }, SidGid::{ sid: 229, gid: 2 },
    SidGid::{ sid: 230, gid: 3 },   SidGid::{ sid: 231, gid: 4 },   SidGid::{ sid: 232, gid: 5 },   SidGid::{ sid: 233, gid: 6 },
    SidGid::{ sid: 234, gid: 7 },   SidGid::{ sid: 235, gid: 8 },   SidGid::{ sid: 236, gid: 9 },   SidGid::{ sid: 237, gid: 10 },
    SidGid::{ sid: 238, gid: 11 },  SidGid::{ sid: 239, gid: 16 },  SidGid::{ sid: 240, gid: 17 },  SidGid::{ sid: 241, gid: 18 },
    SidGid::{ sid: 242, gid: 19 },  SidGid::{ sid: 243, gid: 20 },  SidGid::{ sid: 244, gid: 21 },  SidGid::{ sid: 245, gid: 22 },
    SidGid::{ sid: 246, gid: 23 },  SidGid::{ sid: 247, gid: 24 },  SidGid::{ sid: 248, gid: 25 },  SidGid::{ sid: 249, gid: 28 },
    SidGid::{ sid: 250, gid: 29 },  SidGid::{ sid: 251, gid: 30 },  SidGid::{ sid: 252, gid: 31 },  SidGid::{ sid: 253, gid: 32 },
    SidGid::{ sid: 254, gid: 33 },  SidGid::{ sid: 255, gid: 34 },  SidGid::{ sid: 256, gid: 35 },  SidGid::{ sid: 257, gid: 36 },
    SidGid::{ sid: 258, gid: 37 },  SidGid::{ sid: 259, gid: 38 },  SidGid::{ sid: 260, gid: 39 },  SidGid::{ sid: 261, gid: 40 },
    SidGid::{ sid: 262, gid: 41 },  SidGid::{ sid: 263, gid: 42 },  SidGid::{ sid: 264, gid: 43 },  SidGid::{ sid: 265, gid: 44 },
    SidGid::{ sid: 266, gid: 45 },  SidGid::{ sid: 267, gid: 48 },  SidGid::{ sid: 268, gid: 49 },  SidGid::{ sid: 269, gid: 50 },
    SidGid::{ sid: 270, gid: 51 },  SidGid::{ sid: 271, gid: 52 },  SidGid::{ sid: 272, gid: 53 },  SidGid::{ sid: 273, gid: 54 },
    SidGid::{ sid: 274, gid: 55 },  SidGid::{ sid: 275, gid: 56 },  SidGid::{ sid: 276, gid: 57 },  SidGid::{ sid: 277, gid: 58 },
    SidGid::{ sid: 278, gid: 59 },  SidGid::{ sid: 279, gid: 60 },  SidGid::{ sid: 280, gid: 61 },  SidGid::{ sid: 281, gid: 62 },
    SidGid::{ sid: 282, gid: 63 },  SidGid::{ sid: 283, gid: 64 },  SidGid::{ sid: 284, gid: 65 },  SidGid::{ sid: 285, gid: 66 },
    SidGid::{ sid: 286, gid: 67 },  SidGid::{ sid: 287, gid: 68 },  SidGid::{ sid: 288, gid: 69 },  SidGid::{ sid: 289, gid: 70 },
    SidGid::{ sid: 290, gid: 71 },  SidGid::{ sid: 291, gid: 72 },  SidGid::{ sid: 292, gid: 73 },  SidGid::{ sid: 293, gid: 74 },
    SidGid::{ sid: 294, gid: 75 },  SidGid::{ sid: 295, gid: 76 },  SidGid::{ sid: 296, gid: 77 },  SidGid::{ sid: 297, gid: 78 },
    SidGid::{ sid: 298, gid: 79 },  SidGid::{ sid: 299, gid: 80 },  SidGid::{ sid: 300, gid: 81 },  SidGid::{ sid: 301, gid: 82 },
    SidGid::{ sid: 302, gid: 83 },  SidGid::{ sid: 303, gid: 84 },  SidGid::{ sid: 304, gid: 85 },  SidGid::{ sid: 305, gid: 86 },
    SidGid::{ sid: 306, gid: 87 },  SidGid::{ sid: 307, gid: 88 },  SidGid::{ sid: 308, gid: 89 },  SidGid::{ sid: 309, gid: 90 },
    SidGid::{ sid: 310, gid: 91 },  SidGid::{ sid: 311, gid: 92 },  SidGid::{ sid: 312, gid: 93 },  SidGid::{ sid: 313, gid: 94 },
    SidGid::{ sid: 314, gid: 95 },  SidGid::{ sid: 315, gid: 96 },  SidGid::{ sid: 316, gid: 97 },  SidGid::{ sid: 317, gid: 98 },
    SidGid::{ sid: 318, gid: 99 },  SidGid::{ sid: 319, gid: 103 }, SidGid::{ sid: 320, gid: 104 }, SidGid::{ sid: 321, gid: 105 },
    SidGid::{ sid: 322, gid: 106 }, SidGid::{ sid: 323, gid: 107 }, SidGid::{ sid: 324, gid: 108 }, SidGid::{ sid: 325, gid: 109 },
    SidGid::{ sid: 326, gid: 110 }, SidGid::{ sid: 327, gid: 114 }, SidGid::{ sid: 328, gid: 115 }, SidGid::{ sid: 329, gid: 116 },
    SidGid::{ sid: 330, gid: 117 }, SidGid::{ sid: 331, gid: 118 }, SidGid::{ sid: 332, gid: 119 }, SidGid::{ sid: 333, gid: 120 },
    SidGid::{ sid: 334, gid: 121 }, SidGid::{ sid: 335, gid: 122 }, SidGid::{ sid: 336, gid: 123 }, SidGid::{ sid: 337, gid: 124 },
    SidGid::{ sid: 338, gid: 125 }, SidGid::{ sid: 339, gid: 126 }, SidGid::{ sid: 340, gid: 127 }, SidGid::{ sid: 341, gid: 128 },
    SidGid::{ sid: 342, gid: 129 }, SidGid::{ sid: 343, gid: 130 }, SidGid::{ sid: 344, gid: 131 }, SidGid::{ sid: 345, gid: 132 },
    SidGid::{ sid: 346, gid: 133 }, SidGid::{ sid: 347, gid: 134 }, SidGid::{ sid: 348, gid: 135 }, SidGid::{ sid: 349, gid: 136 },
    SidGid::{ sid: 350, gid: 137 }, SidGid::{ sid: 351, gid: 138 }, SidGid::{ sid: 352, gid: 139 }, SidGid::{ sid: 353, gid: 140 },
    SidGid::{ sid: 354, gid: 141 }, SidGid::{ sid: 355, gid: 142 }, SidGid::{ sid: 356, gid: 143 }, SidGid::{ sid: 357, gid: 144 },
    SidGid::{ sid: 358, gid: 145 }, SidGid::{ sid: 359, gid: 146 }, SidGid::{ sid: 360, gid: 147 }, SidGid::{ sid: 361, gid: 148 },
    SidGid::{ sid: 362, gid: 149 }, SidGid::{ sid: 363, gid: 150 }, SidGid::{ sid: 364, gid: 151 }, SidGid::{ sid: 365, gid: 152 },
    SidGid::{ sid: 366, gid: 153 }, SidGid::{ sid: 367, gid: 154 }, SidGid::{ sid: 368, gid: 155 }, SidGid::{ sid: 369, gid: 156 },
    SidGid::{ sid: 370, gid: 157 }, SidGid::{ sid: 371, gid: 158 }, SidGid::{ sid: 372, gid: 159 }, SidGid::{ sid: 373, gid: 160 },
    SidGid::{ sid: 374, gid: 161 }, SidGid::{ sid: 375, gid: 162 }, SidGid::{ sid: 376, gid: 163 }, SidGid::{ sid: 377, gid: 164 },
    SidGid::{ sid: 378, gid: 165 }
]

let expert_subset_charset_sid_to_gid : Array[SidGid] = [
  SidGid::{ sid: 1, gid: 1 },       SidGid::{ sid: 13, gid: 8 },      SidGid::{ sid: 14, gid: 9 },      SidGid::{ sid: 15, gid: 10 },
  SidGid::{ sid: 27, gid: 22 },     SidGid::{ sid: 28, gid: 23 },     SidGid::{ sid: 99, gid: 11 },     SidGid::{ sid: 109, gid: 41 },
  SidGid::{ sid: 110, gid: 42 },    SidGid::{ sid: 150, gid: 64 },    SidGid::{ sid: 155, gid: 55 },    SidGid::{ sid: 158, gid: 54 },
  SidGid::{ sid: 163, gid: 56 },    SidGid::{ sid: 164, gid: 65 },    SidGid::{ sid: 169, gid: 66 },    SidGid::{ sid: 231, gid: 2 },
  SidGid::{ sid: 232, gid: 3 },     SidGid::{ sid: 235, gid: 4 },     SidGid::{ sid: 236, gid: 5 },     SidGid::{ sid: 237, gid: 6 },
  SidGid::{ sid: 238, gid: 7 },     SidGid::{ sid: 239, gid: 12 },    SidGid::{ sid: 240, gid: 13 },    SidGid::{ sid: 241, gid: 14 },
  SidGid::{ sid: 242, gid: 15 },    SidGid::{ sid: 243, gid: 16 },    SidGid::{ sid: 244, gid: 17 },    SidGid::{ sid: 245, gid: 18 },
  SidGid::{ sid: 246, gid: 19 },    SidGid::{ sid: 247, gid: 20 },    SidGid::{ sid: 248, gid: 21 },    SidGid::{ sid: 249, gid: 24 },
  SidGid::{ sid: 250, gid: 25 },    SidGid::{ sid: 251, gid: 26 },    SidGid::{ sid: 253, gid: 27 },    SidGid::{ sid: 254, gid: 28 },
  SidGid::{ sid: 255, gid: 29 },    SidGid::{ sid: 256, gid: 30 },    SidGid::{ sid: 257, gid: 31 },    SidGid::{ sid: 258, gid: 32 },
  SidGid::{ sid: 259, gid: 33 },    SidGid::{ sid: 260, gid: 34 },    SidGid::{ sid: 261, gid: 35 },    SidGid::{ sid: 262, gid: 36 },
  SidGid::{ sid: 263, gid: 37 },    SidGid::{ sid: 264, gid: 38 },    SidGid::{ sid: 265, gid: 39 },    SidGid::{ sid: 266, gid: 40 },
  SidGid::{ sid: 267, gid: 43 },    SidGid::{ sid: 268, gid: 44 },    SidGid::{ sid: 269, gid: 45 },    SidGid::{ sid: 270, gid: 46 },
  SidGid::{ sid: 272, gid: 47 },    SidGid::{ sid: 300, gid: 48 },    SidGid::{ sid: 301, gid: 49 },    SidGid::{ sid: 302, gid: 50 },
  SidGid::{ sid: 305, gid: 51 },    SidGid::{ sid: 314, gid: 52 },    SidGid::{ sid: 315, gid: 53 },    SidGid::{ sid: 320, gid: 57 },
  SidGid::{ sid: 321, gid: 58 },    SidGid::{ sid: 322, gid: 59 },    SidGid::{ sid: 323, gid: 60 },    SidGid::{ sid: 324, gid: 61 },
  SidGid::{ sid: 325, gid: 62 },    SidGid::{ sid: 326, gid: 63 },    SidGid::{ sid: 327, gid: 67 },    SidGid::{ sid: 328, gid: 68 },
  SidGid::{ sid: 329, gid: 69 },    SidGid::{ sid: 330, gid: 70 },    SidGid::{ sid: 331, gid: 71 },    SidGid::{ sid: 332, gid: 72 },
  SidGid::{ sid: 333, gid: 73 },    SidGid::{ sid: 334, gid: 74 },    SidGid::{ sid: 335, gid: 75 },    SidGid::{ sid: 336, gid: 76 },
  SidGid::{ sid: 337, gid: 77 },    SidGid::{ sid: 338, gid: 78 },    SidGid::{ sid: 339, gid: 79 },    SidGid::{ sid: 340, gid: 80 },
  SidGid::{ sid: 341, gid: 81 },    SidGid::{ sid: 342, gid: 82 },    SidGid::{ sid: 343, gid: 83 },    SidGid::{ sid: 344, gid: 84 },
  SidGid::{ sid: 345, gid: 85 },    SidGid::{ sid: 346, gid: 86 }
]

fn lookup_sid_to_gid(pairs : Array[SidGid], sid : Int) -> Int? {
  let mut lo = 0
  let mut hi = pairs.length()
  while lo < hi {
    let mid = (lo + hi) / 2
    let entry = pairs[mid]
    if sid < entry.sid {
      hi = mid
    } else if sid > entry.sid {
      lo = mid + 1
    } else {
      return Some(entry.gid)
    }
  }
  None
}

///|
pub fn cff1_standard_sid(code : Int) -> Int? {
  if code < 0 || code >= standard_encoding_to_sid.length() {
    return None
  }
  let sid = standard_encoding_to_sid[code]
  if sid == 0 {
    return None
  }
  Some(sid)
}

///|
pub fn cff1_sid_to_gid(
  charset_offset : Int,
  charset_map : Map[Int, Int]?,
  sid : Int,
  glyph_count : Int,
) -> Int? {
  if sid < 0 {
    return None
  }
  let mut gid : Int? = None
  if charset_offset == 0 {
    if sid <= 228 && sid < glyph_count {
      gid = Some(sid)
    }
  } else if charset_offset == 1 {
    gid = lookup_sid_to_gid(expert_charset_sid_to_gid, sid)
  } else if charset_offset == 2 {
    gid = lookup_sid_to_gid(expert_subset_charset_sid_to_gid, sid)
  } else {
    match charset_map {
      None => ()
      Some(map) => gid = map.get(sid)
    }
  }
  match gid {
    None => None
    Some(value) =>
      if value <= 0 || value >= glyph_count { None } else { Some(value) }
  }
}

fn assign_gid_sids(
  pairs : Array[SidGid],
  glyph_count : Int,
  gids : Array[Int],
) -> Unit {
  for entry in pairs {
    if entry.gid >= 0 && entry.gid < glyph_count {
      gids[entry.gid] = entry.sid
    }
  }
}

fn build_gid_to_sid_map(
  charset_offset : Int,
  charset_map : Map[Int, Int]?,
  glyph_count : Int,
) -> Result[Array[Int], CffError] {
  if glyph_count < 0 {
    return Err(InvalidFormat)
  }
  let gids : Array[Int] = Array::make(glyph_count, -1)
  if glyph_count == 0 {
    return Ok(gids)
  }
  gids[0] = 0
  if glyph_count == 1 {
    return Ok(gids)
  }
  if charset_offset == 0 {
    for gid in 1.. 228 {
        return Err(InvalidFormat)
      }
      gids[gid] = gid
    }
    return Ok(gids)
  }
  if charset_offset == 1 {
    assign_gid_sids(expert_charset_sid_to_gid, glyph_count, gids)
    return Ok(gids)
  }
  if charset_offset == 2 {
    assign_gid_sids(expert_subset_charset_sid_to_gid, glyph_count, gids)
    return Ok(gids)
  }
  match charset_map {
    None => Err(InvalidFormat)
    Some(map) => {
      map.eachi((_, sid, gid) => {
        if gid >= 0 && gid < glyph_count {
          gids[gid] = sid
        }
      })
      Ok(gids)
    }
  }
}

///|
pub fn parse_cff1_charset(
  data : BytesView,
  offset : Int,
  glyph_count : Int,
) -> Result[Map[Int, Int], CffError] {
  let values : Map[Int, Int] = {}
  values[0] = 0
  if glyph_count <= 1 {
    return Ok(values)
  }
  let format = read_u8_int(data, offset)
  let format = match format {
    Err(err) => return Err(err)
    Ok(value) => value
  }
  let mut pos = offset + 1
  let mut gid = 1
  if format == 0 {
    while gid < glyph_count {
      let sid = read_u16_int(data, pos)
      let sid = match sid {
        Err(err) => return Err(err)
        Ok(value) => value
      }
      values[sid] = gid
      gid = gid + 1
      pos = pos + 2
    }
    return Ok(values)
  }
  if format == 1 || format == 2 {
    while gid < glyph_count {
      let first = read_u16_int(data, pos)
      let nleft =
        if format == 1 { read_u8_int(data, pos + 2) } else { read_u16_int(data, pos + 2) }
      let first = match first {
        Err(err) => return Err(err)
        Ok(value) => value
      }
      let nleft = match nleft {
        Err(err) => return Err(err)
        Ok(value) => value
      }
      let mut sid = first
      let mut count = nleft
      while count >= 0 && gid < glyph_count {
        values[sid] = gid
        sid = sid + 1
        gid = gid + 1
        count = count - 1
      }
      let step = if format == 1 { 3 } else { 4 }
      pos = pos + step
    }
    return Ok(values)
  }
  Err(InvalidFormat)
}