use tui_input::{Input, InputRequest};

use crate::term::{
  attrs::Attrs,
  grid::Rect,
  key::{Key, KeyCode, KeyEventKind, KeyMods},
  Grid, TermEvent,
};

pub fn render_text_input(
  input: &mut Input,
  area: Rect,
  grid: &mut Grid,
  cursor_pos: &mut (u16, u16),
) {
  let value = input.value();

  let left_trim = input.cursor().saturating_sub(area.width as usize);
  let (value, cursor) = if left_trim > 0 {
    let start =
      unicode_segmentation::UnicodeSegmentation::grapheme_indices(value, true)
        .nth(left_trim)
        .map_or_else(|| value.len(), |(len, _)| len);
    (&value[start..], input.cursor() - left_trim)
  } else {
    (value, input.cursor())
  };

  grid.fill_area(area, ' ', Attrs::default());
  grid.draw_text(area, value, Attrs::default());

  *cursor_pos = (area.x + cursor as u16, area.y);
}

pub fn to_input_request(evt: &TermEvent) -> Option<InputRequest> {
  use InputRequest::*;
  use KeyCode::*;
  match evt {
    TermEvent::Key(Key {
      code,
      mods,
      kind,
      state: _,
    }) if *kind == KeyEventKind::Press || *kind == KeyEventKind::Repeat => {
      match (*code, *mods) {
        (Backspace, KeyMods::NONE) | (Char('h'), KeyMods::CONTROL) => {
          Some(DeletePrevChar)
        }
        (Delete, KeyMods::NONE) => Some(DeleteNextChar),
        (Tab, KeyMods::NONE) => None,
        (Left, KeyMods::NONE) | (Char('b'), KeyMods::CONTROL) => {
          Some(GoToPrevChar)
        }
        (Left, KeyMods::CONTROL) | (Char('b'), KeyMods::META) => {
          Some(GoToPrevWord)
        }
        (Right, KeyMods::NONE) | (Char('f'), KeyMods::CONTROL) => {
          Some(GoToNextChar)
        }
        (Right, KeyMods::CONTROL) | (Char('f'), KeyMods::META) => {
          Some(GoToNextWord)
        }
        (Char('u'), KeyMods::CONTROL) => Some(DeleteLine),

        (Char('w'), KeyMods::CONTROL)
        | (Char('d'), KeyMods::META)
        | (Backspace, KeyMods::META)
        | (Backspace, KeyMods::ALT) => Some(DeletePrevWord),

        (Delete, KeyMods::CONTROL) => Some(DeleteNextWord),
        (Char('k'), KeyMods::CONTROL) => Some(DeleteTillEnd),
        (Char('a'), KeyMods::CONTROL) | (Home, KeyMods::NONE) => {
          Some(GoToStart)
        }
        (Char('e'), KeyMods::CONTROL) | (End, KeyMods::NONE) => Some(GoToEnd),
        (Char(c), KeyMods::NONE) => Some(InsertChar(c)),
        (Char(c), KeyMods::SHIFT) => Some(InsertChar(c)),
        (_, _) => None,
      }
    }
    _ => None,
  }
}
