use crate::filename::NotePath;
use crate::{config::LIB_CFG, content::Content};
use std::path::Path;
#[non_exhaustive]
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub enum TemplateKind {
    New,
    FromClipboardYaml,
    FromClipboard,
    FromTextFile,
    AnnotateFile,
    SyncFilename,
    #[default]
    None,
}
impl TemplateKind {
    pub fn from<T: Content>(path: &Path, clipboard: &T, stdin: &T) -> (Self, Option<T>) {
        let stdin_is_empty = stdin.is_empty();
        let stdin_has_header = !stdin.header().is_empty();
        let clipboard_is_empty = clipboard.is_empty();
        let clipboard_has_header = !clipboard.header().is_empty();
        let input_stream_is_some = !stdin_is_empty || !clipboard_is_empty;
        let input_stream_has_header = stdin_has_header || clipboard_has_header;
        let path_is_dir = path.is_dir();
        let path_is_file = path.is_file();
        let path_has_tpnote_extension = path.has_tpnote_extension();
        let path_is_tpnote_file = path_is_file && path_has_tpnote_extension;
        let (path_is_tpnote_file_and_has_header, content) = if path_is_tpnote_file {
            let content: T = Content::open(path).unwrap_or_default();
            (!content.header().is_empty(), Some(content))
        } else {
            (false, None)
        };
        let template_kind = match (
            path_is_dir,
            input_stream_is_some,
            input_stream_has_header,
            path_is_file,
            path_is_tpnote_file,
            path_is_tpnote_file_and_has_header,
        ) {
            (true, false, _, false, _, _) => TemplateKind::New,
            (true, true, false, false, _, _) => TemplateKind::FromClipboard,
            (true, true, true, false, _, _) => TemplateKind::FromClipboardYaml,
            (false, _, _, true, true, true) => TemplateKind::SyncFilename,
            (false, _, _, true, true, false) => TemplateKind::FromTextFile,
            (false, _, _, true, false, _) => TemplateKind::AnnotateFile,
            (_, _, _, _, _, _) => TemplateKind::None,
        };
        log::debug!("Chosing the \"{:?}\" template.", template_kind);
        log::trace!(
            "Template choice is based on:
             path=\"{}\",
             path_is_dir={},
             input_stream_is_some={},
             input_stream_has_header={},
             path_is_file={},
             path_is_tpnote_file={},
             path_is_tpnote_file_and_has_header={}",
            path.to_str().unwrap(),
            path_is_dir,
            input_stream_is_some,
            input_stream_has_header,
            path_is_file,
            path_is_tpnote_file,
            path_is_tpnote_file_and_has_header,
        );
        (template_kind, content)
    }
    pub fn get_content_template(&self) -> String {
        match self {
            Self::New => LIB_CFG.read().unwrap().tmpl.new_content.clone(),
            Self::FromClipboardYaml => LIB_CFG
                .read()
                .unwrap()
                .tmpl
                .from_clipboard_yaml_content
                .clone(),
            Self::FromClipboard => LIB_CFG.read().unwrap().tmpl.from_clipboard_content.clone(),
            Self::FromTextFile => LIB_CFG.read().unwrap().tmpl.from_text_file_content.clone(),
            Self::AnnotateFile => LIB_CFG.read().unwrap().tmpl.annotate_file_content.clone(),
            Self::SyncFilename => {
                panic!("`TemplateKind::SyncFilename` has no content template")
            }
            Self::None => panic!("`TemplateKind::None` has no content template"),
        }
    }
    pub fn get_content_template_name(&self) -> &str {
        match self {
            Self::New => "tmpl.new_content",
            Self::FromClipboardYaml => "tmpl.from_clipboard_yaml_content",
            Self::FromClipboard => "tmpl.from_clipboard_content",
            Self::FromTextFile => "tmpl.from_text_file_content",
            Self::AnnotateFile => "tmpl.annotate_file_content",
            Self::SyncFilename => "`TemplateKind::SyncFilename` has no content template",
            Self::None => "`TemplateKind::None` has no content template",
        }
    }
    pub fn get_filename_template(&self) -> String {
        match self {
            Self::New => LIB_CFG.read().unwrap().tmpl.new_filename.clone(),
            Self::FromClipboardYaml => LIB_CFG
                .read()
                .unwrap()
                .tmpl
                .from_clipboard_yaml_filename
                .clone(),
            Self::FromClipboard => LIB_CFG.read().unwrap().tmpl.from_clipboard_filename.clone(),
            Self::FromTextFile => LIB_CFG.read().unwrap().tmpl.from_text_file_filename.clone(),
            Self::AnnotateFile => LIB_CFG.read().unwrap().tmpl.annotate_file_filename.clone(),
            Self::SyncFilename => LIB_CFG.read().unwrap().tmpl.sync_filename.clone(),
            Self::None => panic!("`TemplateKind::None` has no filename template"),
        }
    }
    pub fn get_filename_template_name(&self) -> &str {
        match self {
            Self::New => "tmpl.new_filename",
            Self::FromClipboardYaml => "tmpl.from_clipboard_yaml_filename",
            Self::FromClipboard => "tmpl.from_clipboard_filename",
            Self::FromTextFile => "tmpl.from_text_file_filename",
            Self::AnnotateFile => "tmpl.annotate_file_filename",
            Self::SyncFilename => "tmpl.sync_filename",
            Self::None => "`TemplateKind::None` has no filename template",
        }
    }
}