use super::*;

use crate::view::shortcut_labels::secondary_shortcut;

pub(super) fn model(
    this: &PopoverHost,
    repo_id: RepoId,
    commit_id: &CommitId,
    path: &std::path::Path,
) -> ContextMenuModel {
    let is_submodule = this
        .state
        .repos
        .iter()
        .find(|repo| repo.id == repo_id)
        .and_then(|repo| match &repo.history_state.commit_details {
            Loadable::Ready(details) if details.id == *commit_id => details
                .files
                .iter()
                .find(|file| file.path == path)
                .map(|file| file.is_submodule),
            _ => None,
        })
        .unwrap_or(false);

    let mut items = vec![ContextMenuItem::Header(
        path.file_name()
            .and_then(|p| p.to_str().map(ToOwned::to_owned))
            .unwrap_or_else(|| format!("{path:?}"))
            .into(),
    )];
    items.push(ContextMenuItem::Label(
        components::ContextMenuText::path_single_line(path.display().to_string()),
    ));
    if is_submodule {
        let submodule_state = super::submodule::menu_state(this, repo_id, path);
        if let Some(status_label) = super::submodule::status_label(submodule_state.status) {
            items.push(ContextMenuItem::Label(status_label.into()));
        }
        items.push(ContextMenuItem::Separator);
        items.push(ContextMenuItem::Entry {
            label: "Open submodule summary".into(),
            icon: Some("icons/box.svg".into()),
            shortcut: None,
            disabled: false,
            action: Box::new(ContextMenuAction::SelectDiff {
                repo_id,
                target: DiffTarget::Commit {
                    commit_id: commit_id.clone(),
                    path: Some(path.to_path_buf()),
                },
            }),
        });
        items.push(ContextMenuItem::Entry {
            label: "Open submodule".into(),
            icon: Some("icons/open_external.svg".into()),
            shortcut: None,
            disabled: !submodule_state.can_open,
            action: Box::new(ContextMenuAction::OpenRepo {
                path: submodule_state.open_path.clone().unwrap_or_default(),
            }),
        });
        if crate::external_editor::configured_setting().is_some() {
            items.push(ContextMenuItem::Entry {
                label: "Open in code editor".into(),
                icon: Some("icons/open_external.svg".into()),
                shortcut: Some(secondary_shortcut("E").into()),
                disabled: !submodule_state.can_open,
                action: Box::new(ContextMenuAction::OpenInCodeEditor {
                    repo_id: Some(repo_id),
                    path: path.to_path_buf(),
                }),
            });
        }
        if submodule_state.show_load {
            items.push(ContextMenuItem::Entry {
                label: "Load submodule".into(),
                icon: Some("icons/plus.svg".into()),
                shortcut: None,
                disabled: false,
                action: Box::new(ContextMenuAction::LoadSubmodule {
                    repo_id,
                    path: path.to_path_buf(),
                }),
            });
        }
        push_copy_path_entries(&mut items, this, repo_id, path, Some("C".into()));
        return ContextMenuModel::new(items);
    }

    items.push(ContextMenuItem::Separator);
    items.push(ContextMenuItem::Entry {
        label: "Open diff".into(),
        icon: Some("icons/open_external.svg".into()),
        shortcut: None,
        disabled: false,
        action: Box::new(ContextMenuAction::SelectDiff {
            repo_id,
            target: DiffTarget::Commit {
                commit_id: commit_id.clone(),
                path: Some(path.to_path_buf()),
            },
        }),
    });
    items.push(ContextMenuItem::Entry {
        label: "Open file".into(),
        icon: Some("icons/file.svg".into()),
        shortcut: None,
        disabled: false,
        action: Box::new(ContextMenuAction::OpenFile {
            repo_id,
            path: path.to_path_buf(),
        }),
    });
    items.push(ContextMenuItem::Entry {
        label: "Edit file".into(),
        icon: Some("icons/pencil.svg".into()),
        shortcut: None,
        disabled: crate::view::should_bypass_text_file_preview_for_path(path),
        action: Box::new(ContextMenuAction::EditFile {
            repo_id,
            path: path.to_path_buf(),
        }),
    });
    items.push(ContextMenuItem::Entry {
        label: "Open file location".into(),
        icon: Some("icons/folder.svg".into()),
        shortcut: None,
        disabled: false,
        action: Box::new(ContextMenuAction::OpenFileLocation {
            repo_id,
            path: path.to_path_buf(),
        }),
    });
    if crate::external_editor::configured_setting().is_some() {
        items.push(ContextMenuItem::Entry {
            label: "Open in code editor".into(),
            icon: Some("icons/open_external.svg".into()),
            shortcut: Some(secondary_shortcut("E").into()),
            disabled: false,
            action: Box::new(ContextMenuAction::OpenInCodeEditor {
                repo_id: Some(repo_id),
                path: path.to_path_buf(),
            }),
        });
    }
    items.push(ContextMenuItem::Entry {
        label: "File history".into(),
        icon: Some("icons/refresh.svg".into()),
        shortcut: Some("H".into()),
        disabled: false,
        action: Box::new(ContextMenuAction::OpenPopover {
            kind: PopoverKind::FileHistory {
                repo_id,
                path: path.to_path_buf(),
            },
        }),
    });
    if let Some(permalink) = this
        .state
        .repos
        .iter()
        .find(|repo| repo.id == repo_id)
        .and_then(|repo| match &repo.remotes {
            Loadable::Ready(remotes) => crate::view::permalink::file_permalink(
                remotes,
                commit_id.as_ref(),
                &path.display().to_string(),
            ),
            _ => None,
        })
    {
        items.push(ContextMenuItem::Entry {
            label: "Copy file permalink".into(),
            icon: Some("icons/copy.svg".into()),
            shortcut: None,
            disabled: false,
            action: Box::new(ContextMenuAction::CopyText { text: permalink }),
        });
    }
    push_copy_path_entries(&mut items, this, repo_id, path, Some("C".into()));

    ContextMenuModel::new(items)
}
