///|
/// Severity assigned to a terminal-control finding.
pub(all) enum Severity {
  Info
  Warning
  Dangerous
  Critical
} derive(Debug, Eq, Compare)

///|
/// Broad syntactic family of an ECMA-48 event.
pub(all) enum EventKind {
  Text
  C0
  Escape
  Csi
  Osc
  Dcs
  Sos
  Pm
  Apc
  C1
  Invalid
  Truncated
} derive(Debug, Eq)

///|
/// Security-relevant behavior inferred from a control sequence.
pub(all) enum RiskKind {
  Styling
  CursorMovement
  ScreenRewrite
  ScreenErase
  TerminalQuery
  ModeChange
  TitleChange
  Hyperlink
  ClipboardWrite
  Notification
  WorkingDirectory
  FileTransfer
  DeviceControl
  BidirectionalText
  UnknownControl
  MalformedSequence
} derive(Debug, Eq)

///|
/// Action selected by a policy for an event.
pub(all) enum Decision {
  Keep
  Drop
  Mark
} derive(Debug, Eq)

///|
/// One event emitted by the streaming parser.
///
/// `raw` contains the original sequence, `payload` omits introducers and
/// terminators, and `final_byte` is set for CSI/ESC commands that have one.
pub(all) struct Event {
  kind : EventKind
  raw : String
  payload : String
  final_byte : Char?
  offset : Int
  complete : Bool
} derive(Debug, Eq)

///|
/// A human-readable security finding tied to an event offset.
pub(all) struct Finding {
  rule_id : String
  severity : Severity
  risk : RiskKind
  message : String
  offset : Int
  sequence : String
  decision : Decision
} derive(Debug, Eq)

///|
/// Summary counters for an audit run.
pub(all) struct Stats {
  input_chars : Int
  mut text_chars : Int
  mut control_events : Int
  mut info : Int
  mut warnings : Int
  mut dangerous : Int
  mut critical : Int
  mut dropped : Int
  mut marked : Int
} derive(Debug, Eq)

///|
/// Full result returned by `audit`.
pub(all) struct AuditResult {
  plain_text : String
  safe_terminal : String
  events : Array[Event]
  findings : Array[Finding]
  stats : Stats
  failed : Bool
} derive(Debug, Eq)

///|
/// Parser mode that is exposed so callers can inspect streaming state.
pub(all) enum ParserMode {
  Ground
  EscapeStart
  EscapeIntermediate
  CsiEntry
  CsiParam
  CsiIntermediate
  OscString
  OscEscape
  DcsString
  DcsEscape
  SosString
  SosEscape
  PmString
  PmEscape
  ApcString
  ApcEscape
} derive(Debug, Eq)

///|
fn empty_stats(input_chars : Int) -> Stats {
  {
    input_chars,
    text_chars: 0,
    control_events: 0,
    info: 0,
    warnings: 0,
    dangerous: 0,
    critical: 0,
    dropped: 0,
    marked: 0,
  }
}

///|
pub fn severity_rank(severity : Severity) -> Int {
  match severity {
    Info => 0
    Warning => 1
    Dangerous => 2
    Critical => 3
  }
}

///|
pub fn severity_name(severity : Severity) -> String {
  match severity {
    Info => "info"
    Warning => "warning"
    Dangerous => "dangerous"
    Critical => "critical"
  }
}

///|
pub fn risk_name(risk : RiskKind) -> String {
  match risk {
    Styling => "styling"
    CursorMovement => "cursor-movement"
    ScreenRewrite => "screen-rewrite"
    ScreenErase => "screen-erase"
    TerminalQuery => "terminal-query"
    ModeChange => "mode-change"
    TitleChange => "title-change"
    Hyperlink => "hyperlink"
    ClipboardWrite => "clipboard-write"
    Notification => "notification"
    WorkingDirectory => "working-directory"
    FileTransfer => "file-transfer"
    DeviceControl => "device-control"
    BidirectionalText => "bidirectional-text"
    UnknownControl => "unknown-control"
    MalformedSequence => "malformed-sequence"
  }
}

///|
pub fn event_kind_name(kind : EventKind) -> String {
  match kind {
    Text => "text"
    C0 => "c0"
    Escape => "escape"
    Csi => "csi"
    Osc => "osc"
    Dcs => "dcs"
    Sos => "sos"
    Pm => "pm"
    Apc => "apc"
    C1 => "c1"
    Invalid => "invalid"
    Truncated => "truncated"
  }
}