use std::fs::{File, FileTimes};
use std::path;
use std::time::SystemTime;

use crate::commands::cursor_move;
use crate::error::AppResult;
use crate::history::create_dirlist_with_history;
use crate::types::state::AppState;

fn _update_actime(file: &path::Path) -> std::io::Result<()> {
    let now = SystemTime::now();

    // Update both atime and mtime
    let times = FileTimes::new().set_accessed(now).set_modified(now);

    let fhandle = std::fs::File::open(file)?;
    fhandle.set_times(times)
}

fn _create_file(file: &path::Path) -> std::io::Result<()> {
    File::create(file)?;
    Ok(())
}

/// Implements `touch`: updates the current entry's access/modified time (if `arg` is empty), or
/// creates/touches the named file, then refreshes the listing.
pub fn touch_file(app_state: &mut AppState, arg: &str) -> AppResult {
    let curr_tab = app_state.state.tab_state_ref().curr_tab_ref();
    match arg {
        "" => {
            if let Some(selected_file_path) = app_state
                .state
                .tab_state_ref()
                .curr_tab_ref()
                .curr_list_ref()
                .and_then(|s| s.curr_entry_ref())
                .map(|s| s.file_path().to_path_buf())
            {
                _update_actime(&selected_file_path)?
            }
        }
        file_arg => {
            let file = path::PathBuf::from(file_arg);
            if file.exists() {
                _update_actime(file.as_path())?;
            } else {
                _create_file(file.as_path())?;
            }
        }
    }

    let path = curr_tab
        .curr_list_ref()
        .map(|lst| lst.file_path().to_path_buf());

    if let Some(path) = path {
        let new_dirlist = {
            let options = &app_state.config.display_options;
            let tab_options = app_state.state.tab_state_ref().curr_tab_ref().option_ref();
            let history = app_state.state.tab_state_ref().curr_tab_ref().history_ref();

            create_dirlist_with_history(history, path.as_path(), options, tab_options)?
        };
        let history = app_state.state.tab_state_mut().curr_tab_mut().history_mut();
        history.insert(path, new_dirlist);
    }

    if app_state.config.focus_on_create {
        cursor_move::to_path(app_state, path::Path::new(arg))?;
    }

    Ok(())
}
