use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crate::app::{AppAction, HostForm, HostListView, HostPopup, ViewState};
pub fn handle_input(key: KeyEvent, view: &mut ViewState) -> Option<AppAction> {
let hlv = &mut view.host_list;
if hlv.popup.is_some() {
return handle_popup_input(key, hlv);
}
if hlv.search_mode {
return handle_search_input(key, hlv);
}
handle_normal_input(key, hlv)
}
fn handle_normal_input(key: KeyEvent, hlv: &mut HostListView) -> Option<AppAction> {
match key.code {
KeyCode::Down | KeyCode::Char('j') => {
hlv.select_next();
None
}
KeyCode::Up | KeyCode::Char('k') => {
hlv.select_prev();
None
}
KeyCode::Enter => hlv.selected_host_idx().map(AppAction::ConnectAt),
KeyCode::Char('/') => {
hlv.search_mode = true;
None
}
KeyCode::Char('a') => {
hlv.popup = Some(HostPopup::Add(HostForm::empty()));
None
}
KeyCode::Char('e') => {
if hlv.selected_host_idx().is_some() {
Some(AppAction::OpenEditPopup)
} else {
None
}
}
KeyCode::Char('d') => {
if let Some(idx) = hlv.selected_host_idx() {
hlv.popup = Some(HostPopup::DeleteConfirm(idx));
}
None
}
KeyCode::Char('K') => {
if hlv.selected_host_idx().is_some() {
Some(AppAction::StartKeySetup)
} else {
None
}
}
KeyCode::Char('r') => Some(AppAction::ReloadHosts),
_ => None,
}
}
fn handle_search_input(key: KeyEvent, hlv: &mut HostListView) -> Option<AppAction> {
match key.code {
KeyCode::Enter => {
hlv.search_mode = false;
None
}
KeyCode::Esc => {
hlv.search_mode = false;
hlv.search_query.clear();
Some(AppAction::SearchQueryChanged)
}
KeyCode::Backspace => {
hlv.search_query.pop();
Some(AppAction::SearchQueryChanged)
}
KeyCode::Char(c) if !key.modifiers.contains(KeyModifiers::CONTROL) => {
hlv.search_query.push(c);
Some(AppAction::SearchQueryChanged)
}
_ => None,
}
}
fn handle_popup_input(key: KeyEvent, hlv: &mut HostListView) -> Option<AppAction> {
if key.code == KeyCode::Esc {
hlv.popup = None;
return None;
}
match &mut hlv.popup {
Some(HostPopup::Add(form)) | Some(HostPopup::Edit { form, .. }) => {
handle_form_input(key, form)
}
Some(HostPopup::DeleteConfirm(_)) => match key.code {
KeyCode::Char('y') | KeyCode::Char('Y') => Some(AppAction::ConfirmDelete),
KeyCode::Char('n') | KeyCode::Char('N') => {
hlv.popup = None;
None
}
_ => None,
},
Some(HostPopup::KeySetupConfirm(idx)) => match key.code {
KeyCode::Char('y') | KeyCode::Char('Y') | KeyCode::Enter => {
Some(AppAction::ConfirmKeySetup(*idx))
}
KeyCode::Char('n') | KeyCode::Char('N') => Some(AppAction::CancelKeySetup),
_ => None,
},
Some(HostPopup::KeySetupProgress { .. }) => {
None
}
None => None,
}
}
fn handle_form_input(key: KeyEvent, form: &mut HostForm) -> Option<AppAction> {
match key.code {
KeyCode::Enter => Some(AppAction::ConfirmForm),
KeyCode::Tab => {
form.focus_next();
None
}
KeyCode::BackTab => {
form.focus_prev();
None
}
KeyCode::Backspace => {
if let Some(field) = form.fields.get_mut(form.focused_field) {
field.backspace();
}
None
}
KeyCode::Char(c) if !key.modifiers.contains(KeyModifiers::CONTROL) => {
if let Some(field) = form.fields.get_mut(form.focused_field) {
field.insert_char(c);
}
None
}
_ => None,
}
}