///| IEC 61131-3 基础数据类型与 PLC 值表示

///|
pub(all) enum PlcValue {
  Bool(Bool)
  Int(Int)
  Real(Double)
  Time(Int64) // 毫秒数 (ms)
  String(String)
  Null
} derive(Debug)

///|
pub fn PlcValue::is_true(self : PlcValue) -> Bool {
  match self {
    PlcValue::Bool(b) => b
    PlcValue::Int(i) => i != 0
    PlcValue::Real(r) => r != 0.0
    PlcValue::Time(t) => t > 0L
    _ => false
  }
}

///|
pub fn PlcValue::to_int(self : PlcValue) -> Int {
  match self {
    PlcValue::Bool(b) => if b { 1 } else { 0 }
    PlcValue::Int(i) => i
    PlcValue::Real(r) => r.to_int()
    PlcValue::Time(t) => t.to_int()
    _ => 0
  }
}

///|
pub fn PlcValue::to_double(self : PlcValue) -> Double {
  match self {
    PlcValue::Bool(b) => if b { 1.0 } else { 0.0 }
    PlcValue::Int(i) => i.to_double()
    PlcValue::Real(r) => r
    PlcValue::Time(t) => t.to_double()
    _ => 0.0
  }
}

///|
pub fn PlcValue::to_string_repr(self : PlcValue) -> String {
  match self {
    PlcValue::Bool(b) => if b { "TRUE" } else { "FALSE" }
    PlcValue::Int(i) => i.to_string()
    PlcValue::Real(r) => r.to_string()
    PlcValue::Time(t) => "T#\{t}ms"
    PlcValue::String(s) => s
    PlcValue::Null => "NULL"
  }
}

///|
/// 比较相等性
pub fn PlcValue::eq(self : PlcValue, other : PlcValue) -> Bool {
  match (self, other) {
    (PlcValue::Bool(a), PlcValue::Bool(b)) => a == b
    (PlcValue::Int(a), PlcValue::Int(b)) => a == b
    (PlcValue::Real(a), PlcValue::Real(b)) => a == b
    (PlcValue::Time(a), PlcValue::Time(b)) => a == b
    (PlcValue::String(a), PlcValue::String(b)) => a == b
    (PlcValue::Null, PlcValue::Null) => true
    _ => false
  }
}

///|
/// 比较大小 (<)
pub fn PlcValue::lt(self : PlcValue, other : PlcValue) -> Bool {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) => a < b
    (PlcValue::Real(a), PlcValue::Real(b)) => a < b
    (PlcValue::Time(a), PlcValue::Time(b)) => a < b
    _ => false
  }
}

///|
/// 比较大小 (<=)
pub fn PlcValue::lte(self : PlcValue, other : PlcValue) -> Bool {
  self.eq(other) || self.lt(other)
}

///|
/// 加法运算
pub fn PlcValue::add(self : PlcValue, other : PlcValue) -> PlcValue {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) => PlcValue::Int(a + b)
    (PlcValue::Real(a), PlcValue::Real(b)) => PlcValue::Real(a + b)
    (PlcValue::Time(a), PlcValue::Time(b)) => PlcValue::Time(a + b)
    (PlcValue::String(a), PlcValue::String(b)) => PlcValue::String(a + b)
    _ => PlcValue::Null
  }
}

///|
/// 减法运算
pub fn PlcValue::sub(self : PlcValue, other : PlcValue) -> PlcValue {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) => PlcValue::Int(a - b)
    (PlcValue::Real(a), PlcValue::Real(b)) => PlcValue::Real(a - b)
    (PlcValue::Time(a), PlcValue::Time(b)) => PlcValue::Time(a - b)
    _ => PlcValue::Null
  }
}

///|
/// 乘法运算
pub fn PlcValue::mul(self : PlcValue, other : PlcValue) -> PlcValue {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) => PlcValue::Int(a * b)
    (PlcValue::Real(a), PlcValue::Real(b)) => PlcValue::Real(a * b)
    _ => PlcValue::Null
  }
}

///|
/// 除法运算
pub fn PlcValue::div(self : PlcValue, other : PlcValue) -> PlcValue {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) =>
      if b == 0 {
        PlcValue::Null
      } else {
        PlcValue::Int(a / b)
      }
    (PlcValue::Real(a), PlcValue::Real(b)) =>
      if b == 0.0 {
        PlcValue::Null
      } else {
        PlcValue::Real(a / b)
      }
    _ => PlcValue::Null
  }
}

///|
/// 取模运算
pub fn PlcValue::modulo(self : PlcValue, other : PlcValue) -> PlcValue {
  match (self, other) {
    (PlcValue::Int(a), PlcValue::Int(b)) =>
      if b == 0 {
        PlcValue::Null
      } else {
        PlcValue::Int(a % b)
      }
    _ => PlcValue::Null
  }
}

///|
/// PLC 物理/逻辑存储区
pub(all) enum PlcArea {
  Input // %I 输入映像区
  Output // %Q 输出映像区
  Memory // %M 内部标志寄存器区
} derive(Debug, Eq)

///|
/// 寻址大小
pub(all) enum PlcDataSize {
  Bit // X (1 bit)
  Byte // B (8 bits)
  Word // W (16 bits)
  DWord // D (32 bits)
} derive(Debug, Eq)

///|
/// PLC 统一地址定义 (例如 %IX0.0, %QX1.2, %MW10)
pub(all) struct PlcAddress {
  area : PlcArea
  size : PlcDataSize
  byte_offset : Int
  bit_offset : Int
} derive(Debug, Eq)

///|
/// 纯 MoonBit 实现的轻量非负整数解析
pub fn parse_uint_simple(s : String) -> Int {
  let mut res = 0
  let mut i = 0
  while i < s.length() {
    let c = s[i]
    if c >= '0' && c <= '9' {
      let digit = c.to_int() - '0'.to_int()
      res = res * 10 + digit
    }
    i = i + 1
  }
  res
}

///|
/// 将 IEC 61131-3 地址字符串 (如 "%IX0.1", "%QX0.0", "%MW10") 解析为 PlcAddress
pub fn parse_plc_address(addr : String) -> PlcAddress? {
  if !addr.has_prefix("%") || addr.length() < 3 {
    return None
  }
  let area = match addr[1] {
    'I' | 'i' => PlcArea::Input
    'Q' | 'q' => PlcArea::Output
    'M' | 'm' => PlcArea::Memory
    _ => return None
  }
  let mut idx = 2
  let size = match addr[idx] {
    'X' | 'x' => {
      idx = idx + 1
      PlcDataSize::Bit
    }
    'B' | 'b' => {
      idx = idx + 1
      PlcDataSize::Byte
    }
    'W' | 'w' => {
      idx = idx + 1
      PlcDataSize::Word
    }
    'D' | 'd' => {
      idx = idx + 1
      PlcDataSize::DWord
    }
    _ => PlcDataSize::Bit // 默认位寻址
  }

  // 提取数字偏移 byte.bit
  let rem = addr[idx:].to_owned()
  let mut dot_pos = -1
  let mut i = 0
  while i < rem.length() {
    if rem[i] == '.' {
      dot_pos = i
      break
    }
    i = i + 1
  }

  if dot_pos >= 0 {
    let byte_str = rem[0:dot_pos].to_owned()
    let bit_str = rem[dot_pos + 1:].to_owned()
    let byte_val = parse_uint_simple(byte_str)
    let bit_val = parse_uint_simple(bit_str)
    Some({ area, size, byte_offset: byte_val, bit_offset: bit_val, })
  } else {
    let byte_val = parse_uint_simple(rem)
    Some({ area, size, byte_offset: byte_val, bit_offset: 0, })
  }
}