///| IEC 61131-3 结构化文本 (ST) 词法分析器 (Lexer)

///|
/// Token 类型定义
pub(all) enum Token {
  // 关键字
  KwProgram
  KwEndProgram
  KwVar
  KwEndVar
  KwVarInput
  KwVarOutput
  KwAt
  KwIf
  KwThen
  KwElsif
  KwElse
  KwEndIf
  KwWhile
  KwEndWhile
  KwDo
  KwFor
  KwTo
  KwBy
  KwEndFor
  KwAnd
  KwOr
  KwNot
  KwXor
  KwMod

  // 标点与运算符
  Assign // :=
  Equal // =
  NotEqual // <>
  LessThan // <
  LessThanEqual // <=
  GreaterThan // >
  GreaterThanEqual // >=
  Plus // +
  Minus // -
  Star // *
  Slash // /
  LParen // (
  RParen // )
  Comma // ,
  Semicolon // ;
  Colon // :
  Dot // .

  // 字面量与标识符
  Ident(String)
  BoolLit(Bool)
  IntLit(Int)
  RealLit(Double)
  TimeLit(Int64) // 毫秒
  StringLit(String)
  DirectAddr(PlcAddress)
  EOF
} derive(Debug, Eq)

///|
/// 辅助:将字符转为大写
fn to_upper_char(c : Char) -> Char {
  if c >= 'a' && c <= 'z' {
    let diff = 'a'.to_int() - 'A'.to_int()
    (c.to_int() - diff).unsafe_to_char()
  } else {
    c
  }
}

///|
/// 辅助:将字符串转为全大写(用于关键字不区分大小写匹配)
fn to_upper_string(s : String) -> String {
  let mut buf = ""
  let chars : Array[Char] = s.iter().collect()
  let mut i = 0
  while i < chars.length() {
    let uc = to_upper_char(chars[i])
    buf = buf + uc.to_string()
    i = i + 1
  }
  buf
}

///|
/// 辅助:解析时间字面量如 "T#500MS", "T#5S", "T#2M"
fn parse_time_literal(s : String) -> Int64 {
  let upper = to_upper_string(s)
  let mut start_idx = 2
  if upper.has_prefix("TIME#") {
    start_idx = 5
  }

  let body = upper[start_idx:].to_owned()
  let chars : Array[Char] = body.iter().collect()
  let mut total_ms = 0L
  let mut curr_num = 0L
  let mut i = 0

  while i < chars.length() {
    let c = chars[i]
    if c >= '0' && c <= '9' {
      let d = (c.to_int() - '0'.to_int()).to_int64()
      curr_num = curr_num * 10L + d
      i = i + 1
    } else if c == 'M' && i + 1 < chars.length() && chars[i + 1] == 'S' {
      total_ms = total_ms + curr_num
      curr_num = 0L
      i = i + 2
    } else if c == 'S' {
      total_ms = total_ms + curr_num * 1000L
      curr_num = 0L
      i = i + 1
    } else if c == 'M' {
      total_ms = total_ms + curr_num * 60000L
      curr_num = 0L
      i = i + 1
    } else if c == 'H' {
      total_ms = total_ms + curr_num * 3600000L
      curr_num = 0L
      i = i + 1
    } else if c == 'D' {
      total_ms = total_ms + curr_num * 86400000L
      curr_num = 0L
      i = i + 1
    } else {
      i = i + 1
    }
  }

  if curr_num > 0L && total_ms == 0L {
    curr_num
  } else {
    total_ms
  }
}

///|
/// 词法分析器状态
pub(all) struct Lexer {
  chars : Array[Char]
  len : Int
  mut pos : Int
} derive(Debug)

///|
/// 创建 Lexer
pub fn Lexer::new(src : String) -> Lexer {
  let chars : Array[Char] = src.iter().collect()
  { chars, len: chars.length(), pos: 0, }
}

///|
/// 查看当前字符
fn Lexer::peek(self : Lexer) -> Char {
  if self.pos < self.len {
    self.chars[self.pos]
  } else {
    '\u0000'
  }
}

///|
/// 查看下一个字符
fn Lexer::peek_next(self : Lexer) -> Char {
  if self.pos + 1 < self.len {
    self.chars[self.pos + 1]
  } else {
    '\u0000'
  }
}

///|
/// 消耗当前字符
fn Lexer::advance(self : Lexer) -> Char {
  let c = self.peek()
  self.pos = self.pos + 1
  c
}

///|
/// 辅助:截取字符数组转换为 String
fn chars_slice_to_string(chars : Array[Char], start : Int, end : Int) -> String {
  let mut s = ""
  let mut i = start
  while i < end && i < chars.length() {
    s = s + chars[i].to_string()
    i = i + 1
  }
  s
}

///|
/// 跳过空白与注释
fn Lexer::skip_whitespace_and_comments(self : Lexer) -> Unit {
  while self.pos < self.len {
    let c = self.peek()
    if c == ' ' || c == '\t' || c == '\r' || c == '\n' {
      let _ = self.advance()
      continue
    }

    // 单行注释 //
    if c == '/' && self.peek_next() == '/' {
      let _ = self.advance()
      let _ = self.advance()
      while self.pos < self.len && self.peek() != '\n' {
        let _ = self.advance()
      }
      continue
    }

    // 块注释 (* ... *)
    if c == '(' && self.peek_next() == '*' {
      let _ = self.advance()
      let _ = self.advance()
      while self.pos < self.len {
        if self.peek() == '*' && self.peek_next() == ')' {
          let _ = self.advance()
          let _ = self.advance()
          break
        }
        let _ = self.advance()
      }
      continue
    }

    break
  }
}

///|
/// 读取下一个 Token
pub fn Lexer::next_token(self : Lexer) -> Token {
  self.skip_whitespace_and_comments()

  if self.pos >= self.len {
    return Token::EOF
  }

  let c = self.peek()

  // PLC 直接物理地址 %IX0.0, %QX1.2, %MW10
  if c == '%' {
    let start = self.pos
    let _ = self.advance()
    while self.pos < self.len {
      let ch = self.peek()
      if (ch >= 'A' && ch <= 'Z') ||
        (ch >= 'a' && ch <= 'z') ||
        (ch >= '0' && ch <= '9') ||
        ch == '.' {
        let _ = self.advance()
      } else {
        break
      }
    }
    let raw = chars_slice_to_string(self.chars, start, self.pos)
    match parse_plc_address(raw) {
      Some(addr) => return Token::DirectAddr(addr)
      None => return Token::Ident(raw)
    }
  }

  // 标点符号与运算符
  if c == ':' {
    let _ = self.advance()
    if self.peek() == '=' {
      let _ = self.advance()
      return Token::Assign
    }
    return Token::Colon
  }

  if c == '<' {
    let _ = self.advance()
    if self.peek() == '>' {
      let _ = self.advance()
      return Token::NotEqual
    }
    if self.peek() == '=' {
      let _ = self.advance()
      return Token::LessThanEqual
    }
    return Token::LessThan
  }

  if c == '>' {
    let _ = self.advance()
    if self.peek() == '=' {
      let _ = self.advance()
      return Token::GreaterThanEqual
    }
    return Token::GreaterThan
  }

  if c == '=' {
    let _ = self.advance()
    return Token::Equal
  }

  if c == '+' {
    let _ = self.advance()
    return Token::Plus
  }
  if c == '-' {
    let _ = self.advance()
    return Token::Minus
  }
  if c == '*' {
    let _ = self.advance()
    return Token::Star
  }
  if c == '/' {
    let _ = self.advance()
    return Token::Slash
  }
  if c == '(' {
    let _ = self.advance()
    return Token::LParen
  }
  if c == ')' {
    let _ = self.advance()
    return Token::RParen
  }
  if c == ',' {
    let _ = self.advance()
    return Token::Comma
  }
  if c == ';' {
    let _ = self.advance()
    return Token::Semicolon
  }
  if c == '.' {
    let _ = self.advance()
    return Token::Dot
  }

  // 字符串字面量 '...'
  if c == '\'' {
    let _ = self.advance()
    let start = self.pos
    while self.pos < self.len && self.peek() != '\'' {
      let _ = self.advance()
    }
    let str_val = chars_slice_to_string(self.chars, start, self.pos)
    if self.peek() == '\'' {
      let _ = self.advance()
    }
    return Token::StringLit(str_val)
  }

  // 数字字面量 (整数或浮点数)
  if c >= '0' && c <= '9' {
    let start = self.pos
    let mut is_real = false
    while self.pos < self.len {
      let ch = self.peek()
      if ch >= '0' && ch <= '9' {
        let _ = self.advance()
      } else if ch == '.' && self.peek_next() >= '0' && self.peek_next() <= '9' {
        is_real = true
        let _ = self.advance()
      } else {
        break
      }
    }
    let num_str = chars_slice_to_string(self.chars, start, self.pos)
    if is_real {
      return Token::RealLit(parse_uint_simple(num_str).to_double())
    } else {
      return Token::IntLit(parse_uint_simple(num_str))
    }
  }

  // 标识符、关键字、时间字面量 T#...
  if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' {
    let start = self.pos
    while self.pos < self.len {
      let ch = self.peek()
      if (ch >= 'a' && ch <= 'z') ||
        (ch >= 'A' && ch <= 'Z') ||
        (ch >= '0' && ch <= '9') ||
        ch == '_' {
        let _ = self.advance()
      } else if ch == '#' {
        let prefix = to_upper_string(
          chars_slice_to_string(self.chars, start, self.pos),
        )
        if prefix == "T" || prefix == "TIME" {
          let _ = self.advance() // 吃掉 '#'
          while self.pos < self.len {
            let tc = self.peek()
            if (tc >= 'a' && tc <= 'z') ||
              (tc >= 'A' && tc <= 'Z') ||
              (tc >= '0' && tc <= '9') ||
              tc == '_' {
              let _ = self.advance()
            } else {
              break
            }
          }
          let time_raw = chars_slice_to_string(self.chars, start, self.pos)
          return Token::TimeLit(parse_time_literal(time_raw))
        } else {
          break
        }
      } else {
        break
      }
    }

    let raw = chars_slice_to_string(self.chars, start, self.pos)
    let upper = to_upper_string(raw)

    if upper == "PROGRAM" {
      return Token::KwProgram
    }
    if upper == "END_PROGRAM" {
      return Token::KwEndProgram
    }
    if upper == "VAR" {
      return Token::KwVar
    }
    if upper == "END_VAR" {
      return Token::KwEndVar
    }
    if upper == "VAR_INPUT" {
      return Token::KwVarInput
    }
    if upper == "VAR_OUTPUT" {
      return Token::KwVarOutput
    }
    if upper == "AT" {
      return Token::KwAt
    }
    if upper == "IF" {
      return Token::KwIf
    }
    if upper == "THEN" {
      return Token::KwThen
    }
    if upper == "ELSIF" {
      return Token::KwElsif
    }
    if upper == "ELSE" {
      return Token::KwElse
    }
    if upper == "END_IF" {
      return Token::KwEndIf
    }
    if upper == "WHILE" {
      return Token::KwWhile
    }
    if upper == "END_WHILE" {
      return Token::KwEndWhile
    }
    if upper == "DO" {
      return Token::KwDo
    }
    if upper == "FOR" {
      return Token::KwFor
    }
    if upper == "TO" {
      return Token::KwTo
    }
    if upper == "BY" {
      return Token::KwBy
    }
    if upper == "END_FOR" {
      return Token::KwEndFor
    }
    if upper == "AND" {
      return Token::KwAnd
    }
    if upper == "OR" {
      return Token::KwOr
    }
    if upper == "NOT" {
      return Token::KwNot
    }
    if upper == "XOR" {
      return Token::KwXor
    }
    if upper == "MOD" {
      return Token::KwMod
    }
    if upper == "TRUE" {
      return Token::BoolLit(true)
    }
    if upper == "FALSE" {
      return Token::BoolLit(false)
    }

    return Token::Ident(raw)
  }

  // 无法识别字符,跳过
  let _ = self.advance()
  self.next_token()
}

///|
/// 解析全部 Token 到数组
pub fn Lexer::tokenize(self : Lexer) -> Array[Token] {
  let tokens = []
  while true {
    let tok = self.next_token()
    tokens.push(tok)
    if tok == Token::EOF {
      break
    }
  }
  tokens
}