///|
/// Editor - Full-featured text editor component

///|
/// Editor state
pub(all) struct EditorState {
  buffer : TextBuffer
  undo_stack : UndoStack
  filename : String
  mode : SelectionMode
  modified : Bool
}

///|
/// Create empty editor state
pub fn EditorState::new() -> EditorState {
  EditorState::{
    buffer: TextBuffer::new(),
    undo_stack: UndoStack::new(),
    filename: "untitled",
    mode: SelectionMode::Caret,
    modified: false,
  }
}

///|
/// Create editor state from file (not yet implemented)
pub fn EditorState::from_file(path : String) -> EditorState {
  let buffer = TextBuffer::from_file(path)
  EditorState::{
    buffer,
    undo_stack: UndoStack::new(),
    filename: path,
    mode: SelectionMode::Caret,
    modified: false,
  }
}

///|
/// Line numbers gutter component
fn line_gutter(
  line_count : Int,
  current_line : Int,
  gutter_bg : @core.Color,
) -> @core.Component {
  let width = 4
  let fg = @core.Color::rgb(100, 100, 100)
  let bg = gutter_bg
  let current_fg = @core.Color::cyan()
  let current_bg = @core.Color::rgb(40, 40, 50)
  let components : Array[@core.Component] = []
  for i = 1; i <= line_count; i = i + 1 {
    let is_current = i == current_line
    let line_num = i.to_string()
    let padded = " ".repeat(width - line_num.length()) + line_num + " "
    let (actual_fg, actual_bg) = if is_current {
      (current_fg, current_bg)
    } else {
      (fg, bg)
    }
    components.push(text(padded, fg=actual_fg, bg=actual_bg))
  }
  column(
    components,
    bg~,
    height=@types.Dimension::Length(line_count.to_double()),
  )
}

///|
/// Status bar component
fn status_bar(
  state : EditorState,
  status_message : String,
  fg : @core.Color,
  bg : @core.Color,
) -> @core.Component {
  let mode_str = match state.mode {
    SelectionMode::Caret => "NORMAL"
    SelectionMode::VisualChar => "VISUAL"
    SelectionMode::VisualLine => "VISUAL LINE"
    SelectionMode::VisualBlock => "VISUAL BLOCK"
  }
  let cursor = state.buffer.cursor
  let line_info = cursor.row.to_string() + ":" + cursor.col.to_string()
  let modified = if state.modified { "[+]" } else { "" }
  let filename = state.filename + modified
  let mode_text = text(" " + mode_str + " ", fg=@core.Color::cyan(), bg~)
  let pos_text = text(" " + line_info + " ", fg~, bg~)
  let file_text = text(" " + filename + " ", fg~, bg~)
  let msg_text = text(status_message, fg~, bg~)
  row([mode_text, pos_text, file_text, msg_text], bg~)
}

///|
/// Main editor component
pub fn editor(
  state : EditorState,
  fg : @core.Color,
  bg : @core.Color,
  gutter_bg : @core.Color,
  line_fg : @core.Color,
  line_bg : @core.Color,
  min_width : Double,
  min_height : Double,
  show_status : Bool,
  status_message : String,
) -> @core.Component {
  let buffer = state.buffer
  let line_count = buffer.line_count()
  let current_line = buffer.cursor.row

  // Build line gutter
  let gutter = line_gutter(line_count, current_line, gutter_bg)

  // Build content lines
  let content_lines : Array[@core.Component] = []
  for i, line in buffer.lines {
    let line_num = i + 1
    let is_current = line_num == current_line
    let actual_bg = if is_current {
      line_bg
    } else {
      @core.Color::transparent()
    }
    let line_component = text(line + " ", fg=line_fg, bg=actual_bg)
    content_lines.push(line_component)
  }
  let content = column(
    content_lines,
    bg~,
    justify=@types.Alignment::Start,
    align=@types.Alignment::Start,
    height=@types.Dimension::Length(min_height),
  )

  // Build main editor area
  let editor_area = row(
    [gutter, content],
    width=@types.Dimension::Length(min_width),
    min_width=@types.Dimension::Length(min_width),
    height=@types.Dimension::Length(min_height),
  )

  // Build full editor with status bar
  if show_status {
    let editor_with_status = column(
      [editor_area, status_bar(state, status_message, fg, bg)],
      min_width=@types.Dimension::Length(min_width),
      height=@types.Dimension::Length(min_height + 1),
      bg~,
    )
    editor_with_status
  } else {
    let editor_no_status = column(
      [editor_area],
      min_width=@types.Dimension::Length(min_width),
      min_height=@types.Dimension::Length(min_height),
      bg~,
    )
    editor_no_status
  }
}

///|
/// Simple editor (without undo/redo)
pub fn simple_editor(
  buffer : TextBuffer,
  fg : @core.Color,
  bg : @core.Color,
  gutter_bg : @core.Color,
) -> @core.Component {
  let line_count = buffer.line_count()
  let current_line = buffer.cursor.row
  let gutter = line_gutter(line_count, current_line, gutter_bg)
  let content_lines : Array[@core.Component] = []
  for line in buffer.lines {
    content_lines.push(text(line + " ", fg~, bg~))
  }
  let content = column(content_lines, bg~, justify=@types.Alignment::Start)
  row([gutter, content], bg~)
}