///|
pub(all) struct LanguageTag {
  tag : String
  positions : TagElementsPositions
} derive(Debug, Default, Hash, Eq)

///|
enum State {
  Start
  AfterLanguage
  AfterLongLanguage // 主语言 4-8 位,不允许 Extlang
  AfterExtLang
  AfterScript
  AfterRegion
  InExtension(Bool) // true = 期待扩展内容
  InPrivateUse(Bool) // true = 期待私有使用内容
} derive(Hash, Eq)

// 已知的遗留 3 字母变体 (RFC 5646 允许)

///|
let legacy_3letter_variants : Array[StringView] = [
  "BIS", "NIS", "PIN", "SIN", "KNI", "QUI", "JAN", "FON", "SAA", "SBE", "SCO", "SGU",
  "WUU",
]

///|
pub(all) enum SubtagType {
  PrivateUseIntro // "x"
  ExtensionIntro(Char) // 单字母扩展标识符
  Alphabetic(Int) // 纯字母,带长度
  Numeric(Int) // 纯数字,带长度
  Alphanumeric(Int) // 字母数字混合,带长度
  Invalid
}

///|
struct TagElementsPositions {
  language_end : Int
  extlang_end : Int
  script_end : Int
  region_end : Int
  variant_end : Int
  extension_end : Int
} derive(Debug, Default, Hash, Eq)

///|
pub fn LanguageTag::parse(tag : StringView) -> Result[LanguageTag, TagParseErr] {
  match parse_language_tag(tag) {
    Ok(pos) => Ok({ tag: tag.to_owned(), positions: pos })
    Err(e) => Err(e)
  }
}

///|
pub fn LanguageTag::into_str(self : LanguageTag) -> String {
  self.tag
}

///|
pub fn LanguageTag::primary_language(self : LanguageTag) -> String {
  sub_string(self.tag, 0, self.positions.language_end)
}

///|
pub fn LanguageTag::extended_language(self : LanguageTag) -> String? {
  if self.positions.language_end == self.positions.extlang_end {
    None
  } else {
    Some(
      sub_string(
        self.tag,
        self.positions.language_end + 1,
        self.positions.extlang_end,
      ),
    )
  }
}

///|
pub fn LanguageTag::extended_language_subtags(
  self : LanguageTag,
) -> Array[String] {
  let s = self.extended_language().unwrap_or("")
  split_to_strings(s, '-')
}

///|
pub fn LanguageTag::full_language(self : LanguageTag) -> String {
  sub_string(self.tag, 0, self.positions.extlang_end)
}

///|
pub fn LanguageTag::script(self : LanguageTag) -> String? {
  if self.positions.extlang_end == self.positions.script_end {
    None
  } else {
    Some(
      sub_string(
        self.tag,
        self.positions.extlang_end + 1,
        self.positions.script_end,
      ),
    )
  }
}

///|
pub fn LanguageTag::region(self : LanguageTag) -> String? {
  if self.positions.script_end == self.positions.region_end {
    None
  } else {
    Some(
      sub_string(
        self.tag,
        self.positions.script_end + 1,
        self.positions.region_end,
      ),
    )
  }
}

///|
pub fn LanguageTag::variant(self : LanguageTag) -> String? {
  if self.positions.region_end == self.positions.variant_end {
    None
  } else {
    Some(
      sub_string(
        self.tag,
        self.positions.region_end + 1,
        self.positions.variant_end,
      ),
    )
  }
}

///|
pub fn LanguageTag::variant_subtags(self : LanguageTag) -> Array[String] {
  let s = self.variant().unwrap_or("")
  split_to_strings(s, '-')
}

///|
pub fn LanguageTag::extension(self : LanguageTag) -> String? {
  if self.positions.variant_end == self.positions.extension_end {
    None
  } else {
    Some(
      sub_string(
        self.tag,
        self.positions.variant_end + 1,
        self.positions.extension_end,
      ),
    )
  }
}

///|
pub fn LanguageTag::extension_subtags(self : LanguageTag) -> ExtensionsIterator {
  match self.extension() {
    Some(parts) => ExtensionsIterator::ExtensionsIterator(parts)
    None => ExtensionsIterator::ExtensionsIterator("")
  }
}

///|
pub fn LanguageTag::private_use(self : LanguageTag) -> String? {
  // 查找 x 的位置
  let tag_str = self.tag
  if tag_str.find("-x-") is Some(x_pos) {
    // 找到 -x-,私有使用从 x_pos + 1 开始
    Some(sub_string(tag_str, x_pos + 1, tag_str.length()))
  } else if tag_str.has_prefix("x-") {
    // 整个标签就是私有使用
    Some(tag_str)
  } else {
    None
  }
}

///|
pub fn LanguageTag::private_use_subtags(self : LanguageTag) -> Array[String] {
  let opt = self.private_use()
  match opt {
    None => []
    Some(part) => split_to_strings(sub_string(part, 2, part.length()), '-')
  }
}

///|
pub fn LanguageTag::parse_and_normalize(
  tag : String,
) -> Result[LanguageTag, TagParseErr] {
  match normalize_tag(tag) {
    Ok(normalized) => LanguageTag::parse(normalized)
    Err(e) => Err(e)
  }
}

///|
fn parse_primary_language(subtag : String) -> Result[String, TagParseErr] {
  let len = subtag.length()

  // 快速长度过滤
  if len < 2 || len > 8 {
    return Err(TagParseErr::InvalidLanguageLength)
  }

  // 检查是否全为字母
  if !is_alphabetic(subtag) {
    return Err(TagParseErr::ForbiddenChar)
  }

  // 根据长度分类
  match len {
    2 =>
      // 2字母语言代码 (ISO 639-1)
      // 可选:在此处查表验证是否为注册代码,若需宽松模式则直接通过
      Ok(subtag.to_lower())
    3 =>
      // 3字母语言代码 (ISO 639-2/3)
      // 可选:在此处查表验证
      Ok(subtag.to_lower())
    4..=8 =>
      // 4-8字母语言代码 (Registered languages)
      // 标准规定只要格式符合即视为 Well-formed,无需查表
      Ok(subtag.to_lower())
    _ =>
      // 理论上前面已经过滤了 <2 和 >8,这里是防御性编程
      Err(TagParseErr::InvalidLanguageLength)
  }
}

///|
pub impl Show for LanguageTag with fn to_string(self : LanguageTag) -> String {
  self.tag
}

///|
impl FromStr for LanguageTag with fn from_str(tag : StringView) -> LanguageTag {
  match LanguageTag::parse_and_normalize(tag.to_owned()) {
    Err(_e) => LanguageTag::default()
    Ok(lang_tag) => lang_tag
  }
}

///|
fn sub_string(s : String, start : Int, end : Int) -> String {
  if start >= s.length() {
    return ""
  }
  let real_end = if end > s.length() { s.length() } else { end }
  if start >= real_end {
    return ""
  }
  let result = s[start:real_end]
  result.to_owned()
}

///|
fn split_to_strings(s : String, delim : Char) -> Array[String] {
  if s.is_empty() {
    return []
  }
  s
  .split(String::from_array([delim]))
  .map(fn(part) { part.to_owned() })
  .collect()
}

///|
fn parse_language_tag(
  input : StringView,
) -> Result[TagElementsPositions, TagParseErr] {
  if input.is_empty() {
    return Err(TagParseErr::EmptySubtag)
  }
  // Check for grandfathered tags
  for record in grandfathereds {
    if eq_ignore_ascii_case(record, input) {
      let len = input.length()
      return Ok({
        language_end: len,
        extlang_end: len,
        script_end: len,
        region_end: len,
        variant_end: len,
        extension_end: len,
      })
    }
  }

  if input.has_prefix("x-") || input.has_prefix("X-") {
    if !is_alphanumeric_or_dash(input) {
      return Err(TagParseErr::ForbiddenChar)
    }
    if input.length() == 2 {
      return Err(TagParseErr::EmptyPrivateUse)
    }
    let len = input.length()
    return Ok({
      language_end: len,
      extlang_end: len,
      script_end: len,
      region_end: len,
      variant_end: len,
      extension_end: len,
    })
  }

  calculate_positions(input)
}

///|
fn split_with_positions(input : StringView) -> Iter[(String, Int)] {
  // 返回 (subtag, end_position) 对
  // end_position 是 subtag 结束位置的索引
  let mut pos = 0
  let results = []
  for subtag in input.split("-") {
    let s = subtag.to_owned()
    pos += s.length() + 1
    results.push((s, pos - 1))
  }
  results.iter()
}

///|
fn calculate_positions(
  input : StringView,
) -> Result[TagElementsPositions, TagParseErr] {
  let mut state = State::Start
  let mut language_end = 0
  let mut extlang_end = 0
  let mut script_end = 0
  let mut region_end = 0
  let mut variant_end = 0
  let mut extension_end = 0
  let mut extlangs_count = 0

  for item in split_with_positions(input) {
    let subtag = item.0
    let end = item.1

    if subtag.is_empty() {
      return Err(TagParseErr::EmptySubtag)
    }
    if subtag.length() > 8 {
      return Err(TagParseErr::SubtagTooLong)
    }

    match state {
      State::Start =>
        // 使用专用的解析函数处理主语言子标签
        match parse_primary_language(subtag) {
          Ok(_normalized_lang) => {
            language_end = end
            let len = subtag.length()
            // 2-3 字母后可能跟扩展语言 (extlang)
            // 4-8 字母后不能跟扩展语言,直接进入脚本/地区判断阶段
            state = if len <= 3 {
              State::AfterLanguage
            } else {
              State::AfterLongLanguage // 4-8 位主语言
            }
          }
          Err(e) => return Err(e)
        }
      State::InPrivateUse(_expected) => {
        // 私有使用内容
        if subtag.is_empty() || subtag.length() > 8 {
          return Err(TagParseErr::InvalidSubtag)
        }
        // 不检查 is_alphanumeric
        state = State::InPrivateUse(false)
      }
      _ => {
        // 1. 扩展语言(排除旧式3字母变体)
        if (state == State::AfterLanguage || state == State::AfterExtLang) &&
          subtag.length() == 3 &&
          is_alphabetic(subtag) {
          if !legacy_3letter_variants.contains(subtag.to_lower()) {
            extlangs_count += 1
            if extlangs_count > 3 {
              return Err(TagParseErr::TooManyExtlangs)
            }
            extlang_end = end
            state = State::AfterExtLang
            continue
          }
        }

        // 2. 私有使用引入
        if subtag == "x" || subtag == "X" {
          if state is State::InExtension(true) {
            return Err(TagParseErr::EmptyExtension)
          }
          state = State::InPrivateUse(true)
          continue
        }

        // 3. 扩展引入(单字母)
        if subtag.length() == 1 && is_alphanumeric(subtag) {
          if state is State::InExtension(true) {
            return Err(TagParseErr::EmptyExtension)
          }
          state = State::InExtension(true)
          continue
        }

        // 4. 扩展内容
        if state is State::InExtension(_) {
          if !is_alphanumeric(subtag) {
            return Err(TagParseErr::InvalidSubtag)
          }
          extension_end = end
          state = State::InExtension(false)
          continue
        }

        // 5. 脚本
        if (
            state == State::AfterLanguage ||
            state == State::AfterExtLang ||
            state == State::AfterLongLanguage
          ) &&
          subtag.length() == 4 &&
          is_alphabetic(subtag) {
          script_end = end
          state = State::AfterScript
          continue
        }

        // 6. 地区
        if (
            state == State::AfterLanguage ||
            state == State::AfterExtLang ||
            state == State::AfterLongLanguage ||
            state == State::AfterScript
          ) &&
          (
            (subtag.length() == 2 && is_alphabetic(subtag)) ||
            (subtag.length() == 3 && is_numeric(subtag))
          ) {
          region_end = end
          state = State::AfterRegion
          continue
        }

        // 7. 变体(包括旧式3字母变体)
        if (
            state == State::AfterLanguage ||
            state == State::AfterExtLang ||
            state == State::AfterScript ||
            state == State::AfterRegion
          ) &&
          is_alphanumeric(subtag) &&
          (
            (subtag.length() >= 5 && is_alphabetic(subtag[0:1])) ||
            (subtag.length() >= 4 && is_numeric(subtag[0:1])) ||
            legacy_3letter_variants.contains(subtag.to_lower())
          ) {
          variant_end = end
          state = State::AfterRegion
          continue
        }

        return Err(TagParseErr::InvalidSubtag)
      }
    }
  }

  // 结束检查
  if state is State::InExtension(true) {
    return Err(TagParseErr::EmptyExtension)
  }
  if state is State::InPrivateUse(true) {
    return Err(TagParseErr::EmptyPrivateUse)
  }

  // 设置默认值
  if extlang_end < language_end {
    extlang_end = language_end
  }
  if script_end < extlang_end {
    script_end = extlang_end
  }
  if region_end < script_end {
    region_end = script_end
  }
  if variant_end < region_end {
    variant_end = region_end
  }
  if extension_end < variant_end {
    extension_end = variant_end
  }
  if extension_end == 0 {
    extension_end = input.length()
  }

  Ok({
    language_end,
    extlang_end,
    script_end,
    region_end,
    variant_end,
    extension_end,
  })
}

///|
fn normalize_tag(input : StringView) -> Result[String, TagParseErr] {
  for record in grandfathereds {
    if eq_ignore_ascii_case(record, input) {
      return Ok(record.to_owned())
    }
  }

  if input.has_prefix("x-") || input.has_prefix("X-") {
    if !is_alphanumeric_or_dash(input) {
      return Err(TagParseErr::ForbiddenChar)
    }
    if input.length() == 2 {
      return Err(TagParseErr::EmptyPrivateUse)
    }
    // 私有使用标签整体小写
    return Ok(String::to_lower(input.to_owned()))
  }

  let result = StringBuilder::new()
  let mut is_first = true
  let mut is_private_use = false
  let mut is_in_extension = false // <--- 新增:标记是否处于扩展部分
  let mut is_primary = true // 新增标志

  for subtag in input.split("-") {
    let subtag_str = subtag.to_owned()
    if subtag_str.is_empty() {
      return Err(TagParseErr::EmptySubtag)
    }
    if subtag_str.length() > 8 {
      return Err(TagParseErr::SubtagTooLong)
    }

    if !is_first {
      result.write_string("-")
    }
    is_first = false

    // 检查是否进入私有使用部分
    if !is_private_use && (subtag_str == "x" || subtag_str == "X") {
      is_private_use = true
      is_in_extension = false // 私有使用开始,扩展结束

      result.write_string("x")
      continue
    }
    if !is_private_use &&
      !is_in_extension &&
      subtag_str.length() == 1 &&
      is_alphanumeric(subtag_str) {
      is_in_extension = true
      result.write_string(String::to_lower(subtag_str))
      continue
    }

    if is_private_use {
      // 私有子标签始终小写
      result.write_string(String::to_lower(subtag_str))
    } else if is_in_extension {
      // 扩展子标签始终小写
      result.write_string(String::to_lower(subtag_str))
    } else if is_primary { // ✅ 使用标志
      // 主语言子标签:小写
      result.write_string(String::to_lower(subtag_str))
      is_primary = false
    } else if subtag_str.length() == 3 && is_alphabetic(subtag_str) {
      // 扩展语言子标签:小写
      result.write_string(String::to_lower(subtag_str))
    } else if subtag_str.length() == 4 && is_alphabetic(subtag_str) {
      // 脚本子标签:标题大小写 (Latn)
      result.write_string(to_title_case(subtag_str))
    } else if (subtag_str.length() == 2 && is_alphabetic(subtag_str)) ||
      (subtag_str.length() == 3 && is_numeric(subtag_str)) {
      // 地区子标签:大写 (US, 419)
      result.write_string(String::to_upper(subtag_str))
    } else {
      // 变体和其他:小写
      result.write_string(String::to_lower(subtag_str))
    }
  }
  Ok(result.to_string())
}

///|
pub(all) struct ExtensionsIterator {
  input : String
  subtags : Array[String]
  index : Int
}

///|
fn ExtensionsIterator::ExtensionsIterator(input : String) -> ExtensionsIterator {
  let subtags = if input.is_empty() { [] } else { split_to_strings(input, '-') }
  { input, subtags, index: 0 }
}

///|
pub fn ExtensionsIterator::next(
  self : ExtensionsIterator,
) -> (String?, ExtensionsIterator) {
  if self.index >= self.subtags.length() {
    (None, self)
  } else {
    let tag = self.subtags[self.index]
    let next_iter = {
      input: self.input,
      subtags: self.subtags,
      index: self.index + 1,
    }
    (Some(tag), next_iter)
  }
}

///|
pub fn classify_subtag(s : StringView) -> SubtagType {
  if s.is_empty() {
    return SubtagType::Invalid
  }

  if s == "x" || s == "X" {
    return SubtagType::PrivateUseIntro
  }
  if s.length() == 1 && is_alphanumeric(s) {
    match StringView::get_char(s, 0) {
      Some(c) => return SubtagType::ExtensionIntro(c)
      None => return SubtagType::Invalid // 理论上不会执行
    }
  }

  let is_alpha = is_alphabetic(s)
  let is_num = is_numeric(s)
  let len = s.length()

  if is_alpha {
    return SubtagType::Alphabetic(len)
  }
  if is_num {
    return SubtagType::Numeric(len)
  }
  if is_alphanumeric(s) {
    return SubtagType::Alphanumeric(len)
  }

  SubtagType::Invalid
}

///|
let grandfathereds : Array[StringView] = [
  "art-lojban", "cel-gaulish", "en-GB-oed", "i-ami", "i-bnn", "i-default", "i-enochian",
  "i-hak", "i-klingon", "i-lux", "i-mingo", "i-navajo", "i-pwn", "i-tao", "i-tay",
  "i-tsu", "no-bok", "no-nyn", "sgn-BE-FR", "sgn-BE-NL", "sgn-CH-DE", "zh-guoyu",
  "zh-hakka", "zh-min", "zh-min-nan", "zh-xiang",
]