///|
/// Code 128 的 107 个图案(0-105 为 11 模块,106 停止符为 13 模块)。
///
/// 表格由 `scripts/gen_code128_table.py` 依据 ZXing `Code128Reader#CODE_PATTERNS`
/// 的条空宽度数组生成(图案本身为公开标准数据)。
let code128_patterns : Array[String] = [
  "11011001100", // 0
   "11001101100", // 1
   "11001100110", // 2
   "10010011000", // 3
   "10010001100", // 4
   "10001001100", // 5
   "10011001000", // 6
   "10011000100", // 7
   "10001100100", // 8
   "11001001000", // 9
   "11001000100", // 10
   "11000100100", // 11
   "10110011100", // 12
   "10011011100", // 13
   "10011001110", // 14
   "10111001100", // 15
   "10011101100", // 16
   "10011100110", // 17
   "11001110010", // 18
   "11001011100", // 19
   "11001001110", // 20
   "11011100100", // 21
   "11001110100", // 22
   "11101101110", // 23
   "11101001100", // 24
   "11100101100", // 25
   "11100100110", // 26
   "11101100100", // 27
   "11100110100", // 28
   "11100110010", // 29
   "11011011000", // 30
   "11011000110", // 31
   "11000110110", // 32
   "10100011000", // 33
   "10001011000", // 34
   "10001000110", // 35
   "10110001000", // 36
   "10001101000", // 37
   "10001100010", // 38
   "11010001000", // 39
   "11000101000", // 40
   "11000100010", // 41
   "10110111000", // 42
   "10110001110", // 43
   "10001101110", // 44
   "10111011000", // 45
   "10111000110", // 46
   "10001110110", // 47
   "11101110110", // 48
   "11010001110", // 49
   "11000101110", // 50
   "11011101000", // 51
   "11011100010", // 52
   "11011101110", // 53
   "11101011000", // 54
   "11101000110", // 55
   "11100010110", // 56
   "11101101000", // 57
   "11101100010", // 58
   "11100011010", // 59
   "11101111010", // 60
   "11001000010", // 61
   "11110001010", // 62
   "10100110000", // 63
   "10100001100", // 64
   "10010110000", // 65
   "10010000110", // 66
   "10000101100", // 67
   "10000100110", // 68
   "10110010000", // 69
   "10110000100", // 70
   "10011010000", // 71
   "10011000010", // 72
   "10000110100", // 73
   "10000110010", // 74
   "11000010010", // 75
   "11001010000", // 76
   "11110111010", // 77
   "11000010100", // 78
   "10001111010", // 79
   "10100111100", // 80
   "10010111100", // 81
   "10010011110", // 82
   "10111100100", // 83
   "10011110100", // 84
   "10011110010", // 85
   "11110100100", // 86
   "11110010100", // 87
   "11110010010", // 88
   "11011011110", // 89
   "11011110110", // 90
   "11110110110", // 91
   "10101111000", // 92
   "10100011110", // 93
   "10001011110", // 94
   "10111101000", // 95
   "10111100010", // 96
   "11110101000", // 97
   "11110100010", // 98
   "10111011110", // 99
   "10111101110", // 100
   "11101011110", // 101
   "11110101110", // 102
   "11010000100", // 103
   "11010010000", // 104
   "11010011100", // 105
   "1100011101011", // 106
]

///|
/// 起始码 A(103)/ B(104)/ C(105)、切换码、FNC1 等常量。
let code128_start_a : Int = 103

///|
let code128_start_b : Int = 104

///|
let code128_start_c : Int = 105

///|
let code128_stop : Int = 106

///|
let code128_code_c : Int = 99

///|
let code128_code_b : Int = 100

///|
let code128_code_a : Int = 101

///|
let code128_fnc1 : Int = 102

///|
/// 判断字节是否为 ASCII 数字。
fn is_ascii_digit(c : Byte) -> Bool {
  c >= b'0' && c <= b'9'
}

///|
/// 从位置 `pos` 开始统计连续数字的个数。
fn digit_run(b : Bytes, pos : Int) -> Int {
  let mut n = 0
  let mut i = pos
  while i < b.length() && is_ascii_digit(b[i]) {
    n = n + 1
    i = i + 1
  }
  n
}

///|
/// 将数据编码为 Code 128 值序列(含子集切换,不含起始码与校验码)。
/// 返回 (values, start_code)。起始码按首个字符段选择 A/B/C。
fn code128_values(data : String) -> Result[(Array[Int], Int), String] {
  let b = @utf8.encode(data)
  if b.length() == 0 {
    return Err("Code 128 data must not be empty")
  }
  for i = 0; i < b.length(); i = i + 1 {
    let n = b[i].to_int()
    if n > 127 {
      return Err("Code 128 supports ASCII characters only")
    }
  }
  let values : Array[Int] = []
  let mut pos = 0
  let mut mode : Int? = None
  while pos < b.length() {
    let run = digit_run(b, pos)
    if run >= 4 && pos + 1 < b.length() {
      // 进入/保持 Code C,按两位一组消费偶数个数字。
      match mode {
        Some(m) if m == code128_start_c => ()
        None => mode = Some(code128_start_c)
        Some(_) => {
          values.push(code128_code_c)
          mode = Some(code128_start_c)
        }
      }
      let pairs = if run % 2 == 0 { run } else { run - 1 }
      let mut consumed = 0
      while consumed < pairs {
        let v = (b[pos] - b'0').to_int() * 10 + (b[pos + 1] - b'0').to_int()
        values.push(v)
        pos = pos + 2
        consumed = consumed + 2
      }
      if pairs < run {
        // 奇数位剩余 1 个数字:切回 B 编码该位。
        match mode {
          Some(m) if m == code128_start_b => ()
          None => mode = Some(code128_start_b)
          Some(_) => {
            values.push(code128_code_b)
            mode = Some(code128_start_b)
          }
        }
        values.push(b[pos].to_int() - 32)
        pos = pos + 1
      }
    } else {
      let n = b[pos].to_int()
      if n < 32 {
        // 控制字符只能编码在 Code A。
        match mode {
          Some(m) if m == code128_start_a => ()
          None => mode = Some(code128_start_a)
          Some(_) => {
            values.push(code128_code_a)
            mode = Some(code128_start_a)
          }
        }
        values.push(n + 64)
      } else {
        // 可打印字符(32-127)默认 Code B;若处于 C 则切换。
        match mode {
          Some(m) if m == code128_start_b => ()
          Some(m) if m == code128_start_a => ()
          None => mode = Some(code128_start_b)
          Some(_) => {
            values.push(code128_code_b)
            mode = Some(code128_start_b)
          }
        }
        values.push(n - 32)
      }
      pos = pos + 1
    }
  }
  let start = match mode {
    None => code128_start_b
    Some(m) => m
  }
  Ok((values, start))
}

///|
/// 计算 Code 128 校验值(mod-103,含起始码,权重从 1 递增)。
pub fn code128_checksum(
  data : String,
  gs1? : Bool = false,
) -> Result[Int, String] {
  match code128_values(data) {
    Err(msg) => Err(msg)
    Ok((values, start)) => {
      let mut total = start
      if gs1 {
        total = total + code128_fnc1 * 1
      }
      for i = 0; i < values.length(); i = i + 1 {
        total = total + values[i] * (i + 1)
      }
      Ok(total % 103)
    }
  }
}

///|
/// 编码 Code 128(含子集 A/B/C 自动选择)。
///
/// `gs1` 为 true 时生成 GS1-128:起始码后紧跟 FNC1。
/// 输出结构:起始码 + 数据(含子集切换)+ [FNC1] + 校验码 + 停止符(13 模块)。
pub fn encode_code128(
  data : String,
  gs1? : Bool = false,
) -> Result[Barcode, EncodeError] {
  match code128_values(data) {
    Err(msg) => Err(InvalidData(msg))
    Ok((values, start)) => {
      let mut total = start
      if gs1 {
        total = total + code128_fnc1
      }
      for i = 0; i < values.length(); i = i + 1 {
        total = total + values[i] * (i + 1)
      }
      let check = total % 103
      let modules : Array[Bool] = []
      append_code128_pattern(modules, code128_patterns[start])
      if gs1 {
        append_code128_pattern(modules, code128_patterns[code128_fnc1])
      }
      for v in values {
        append_code128_pattern(modules, code128_patterns[v])
      }
      append_code128_pattern(modules, code128_patterns[check])
      append_code128_pattern(modules, code128_patterns[code128_stop])
      Ok({ symbology: Code128, data, modules })
    }
  }
}

///|
/// 追加一个 Code 128 图案(11 或 13 模块)。
fn append_code128_pattern(modules : Array[Bool], pattern : String) -> Unit {
  let p = @utf8.encode(pattern)
  for i = 0; i < p.length(); i = i + 1 {
    modules.push(p[i] == b'1')
  }
}

///|
/// 校验 Code 128 数据是否可编码。
pub fn validate_code128(
  data : String,
  gs1? : Bool = false,
) -> Result[Unit, EncodeError] {
  match encode_code128(data, gs1~) {
    Err(e) => Err(e)
    Ok(_) => Ok(())
  }
}