// SPDX-FileCopyrightText: 2025 Andrey Kutejko <andy128k@gmail.com>
// SPDX-FileCopyrightText: 2026 Wladimir Palant https://palant.info/
//
// SPDX-License-Identifier: GPL-3.0-or-later

use super::common::create_category;
use crate::{
    dialogs::options::common::{radio_group_get_value, radio_group_set_value},
    file_list::quick_search::QuickSearchMode,
    options::{GeneralOptions, types::WriteResult},
    types::{
        LeftMouseButtonMode, MiddleMouseButtonMode, QuickSearchShortcut, RightMouseButtonMode,
    },
};
use gettextrs::gettext;
use gtk::prelude::*;

pub struct GeneralTab {
    scrolled_window: gtk::ScrolledWindow,
    lmb_single_click: gtk::CheckButton,
    lmb_double_click: gtk::CheckButton,
    lmb_unselects: gtk::CheckButton,
    mmb_cd_up: gtk::CheckButton,
    mmb_new_tab: gtk::CheckButton,
    rmb_popup: gtk::CheckButton,
    rmb_select: gtk::CheckButton,
    delete_to_trash: gtk::CheckButton,
    select_dirs: gtk::CheckButton,
    case_sensitive: gtk::CheckButton,
    quick_search_mode_search: gtk::CheckButton,
    quick_search_mode_filter: gtk::CheckButton,
    quick_search_ctrl_alt: gtk::CheckButton,
    quick_search_alt: gtk::CheckButton,
    quick_search_just_char: gtk::CheckButton,
    search_window_always_on_top: gtk::CheckButton,
    single_instance: gtk::CheckButton,
    save_dirs: gtk::CheckButton,
    save_tabs: gtk::CheckButton,
    save_dir_history: gtk::CheckButton,
    save_cmdline_history: gtk::CheckButton,
    save_search_history: gtk::CheckButton,
}

impl GeneralTab {
    pub fn new() -> Self {
        let vbox = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .margin_top(6)
            .margin_bottom(6)
            .margin_start(6)
            .margin_end(6)
            .hexpand(true)
            .vexpand(true)
            .build();

        let scrolled_window = gtk::ScrolledWindow::builder()
            .hscrollbar_policy(gtk::PolicyType::Never)
            .vscrollbar_policy(gtk::PolicyType::Automatic)
            .hexpand(true)
            .vexpand(true)
            .child(&vbox)
            .build();

        let left_mouse_button = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(
            &gettext("Left mouse button"),
            &left_mouse_button,
        ));
        let lmb_single_click = gtk::CheckButton::builder()
            .label(gettext("Single click to open items"))
            .build();
        left_mouse_button.append(&lmb_single_click);
        let lmb_double_click = gtk::CheckButton::builder()
            .label(gettext("Double click to open items"))
            .group(&lmb_single_click)
            .build();
        left_mouse_button.append(&lmb_double_click);
        let lmb_unselects = gtk::CheckButton::builder()
            .label(gettext("Single click unselects files"))
            .build();
        left_mouse_button.append(&lmb_unselects);

        let middle_mouse_button = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(
            &gettext("Middle mouse button"),
            &middle_mouse_button,
        ));
        let mmb_cd_up = gtk::CheckButton::builder()
            .label(gettext("Up one directory"))
            .build();
        middle_mouse_button.append(&mmb_cd_up);
        let mmb_new_tab = gtk::CheckButton::builder()
            .label(gettext("Opens new tab"))
            .group(&mmb_cd_up)
            .build();
        middle_mouse_button.append(&mmb_new_tab);

        let right_mouse_button = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(
            &gettext("Right mouse button"),
            &right_mouse_button,
        ));
        let rmb_popup = gtk::CheckButton::builder()
            .label(gettext("Shows popup menu"))
            .build();
        right_mouse_button.append(&rmb_popup);
        let rmb_select = gtk::CheckButton::builder()
            .label(gettext("Selects files"))
            .group(&rmb_popup)
            .build();
        right_mouse_button.append(&rmb_select);

        let deletion = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Deletion"), &deletion));
        let delete_to_trash = gtk::CheckButton::builder()
            .label(gettext("Move to trash"))
            .build();
        deletion.append(&delete_to_trash);

        let selection = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Selection"), &selection));
        let select_dirs = gtk::CheckButton::builder()
            .label(gettext("Select directories"))
            .build();
        selection.append(&select_dirs);

        let sorting = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Sorting"), &sorting));
        let case_sensitive = gtk::CheckButton::builder()
            .label(gettext("Case sensitive"))
            .build();
        sorting.append(&case_sensitive);

        let quick_search = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Quick search"), &quick_search));

        let quick_search_mode = gtk::Box::builder()
            .orientation(gtk::Orientation::Horizontal)
            .spacing(6)
            .build();
        quick_search_mode.append(
            &gtk::Label::builder()
                .label(gettext("Default mode:"))
                .build(),
        );
        let quick_search_mode_search = gtk::CheckButton::builder().label(gettext("Search")).build();
        quick_search_mode.append(&quick_search_mode_search);
        let quick_search_mode_filter = gtk::CheckButton::builder()
            .label(gettext("Filter"))
            .group(&quick_search_mode_search)
            .build();
        quick_search_mode.append(&quick_search_mode_filter);
        quick_search.append(&quick_search_mode);

        let quick_search_ctrl_alt = gtk::CheckButton::builder()
            .label(gettext("CTRL+ALT+letters"))
            .build();
        quick_search.append(&quick_search_ctrl_alt);
        let quick_search_alt = gtk::CheckButton::builder()
            .label(gettext("ALT+letters (menu access with F10)"))
            .group(&quick_search_ctrl_alt)
            .build();
        quick_search.append(&quick_search_alt);
        let quick_search_just_char = gtk::CheckButton::builder()
            .label(gettext(
                "Just letters (command line access with CTRL+ALT+C)",
            ))
            .group(&quick_search_ctrl_alt)
            .build();
        quick_search.append(&quick_search_just_char);

        let search_window = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Search Window"), &search_window));
        let search_window_always_on_top = gtk::CheckButton::builder()
            .label(gettext("Search window is always on top"))
            .build();
        search_window.append(&search_window_always_on_top);

        let mutiple_instances = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(
            &gettext("Multiple instances"),
            &mutiple_instances,
        ));
        let single_instance = gtk::CheckButton::builder()
            .label(gettext("Don’t start a new instance"))
            .build();
        mutiple_instances.append(&single_instance);

        let save_on_exit = gtk::Box::builder()
            .orientation(gtk::Orientation::Vertical)
            .spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Save on exit"), &save_on_exit));
        let save_dirs = gtk::CheckButton::builder()
            .label(gettext("Directories"))
            .build();
        save_on_exit.append(&save_dirs);
        let save_tabs = gtk::CheckButton::builder().label(gettext("Tabs")).build();
        save_on_exit.append(&save_tabs);
        let save_dir_history = gtk::CheckButton::builder()
            .label(gettext("Directory history"))
            .build();
        save_on_exit.append(&save_dir_history);
        let save_cmdline_history = gtk::CheckButton::builder()
            .label(gettext("Commandline history"))
            .build();
        save_on_exit.append(&save_cmdline_history);
        let save_search_history = gtk::CheckButton::builder()
            .label(gettext("Search history"))
            .build();
        save_on_exit.append(&save_search_history);

        // Saving directories is implied if we are saving tabs or directory history
        fn update_state(
            save_dirs: &gtk::CheckButton,
            save_tabs: &gtk::CheckButton,
            save_dir_history: &gtk::CheckButton,
        ) {
            if save_tabs.is_active() || save_dir_history.is_active() {
                save_dirs.set_active(true);
            }
            save_dirs.set_sensitive(!(save_tabs.is_active() || save_dir_history.is_active()));
        }

        save_tabs.connect_active_notify(glib::clone!(
            #[weak]
            save_dirs,
            #[weak]
            save_dir_history,
            move |save_tabs| update_state(&save_dirs, save_tabs, &save_dir_history)
        ));
        save_dir_history.connect_active_notify(glib::clone!(
            #[weak]
            save_dirs,
            #[weak]
            save_tabs,
            move |save_dir_history| update_state(&save_dirs, &save_tabs, save_dir_history)
        ));

        Self {
            scrolled_window,
            lmb_single_click,
            lmb_double_click,
            lmb_unselects,
            mmb_cd_up,
            mmb_new_tab,
            rmb_popup,
            rmb_select,
            delete_to_trash,
            select_dirs,
            case_sensitive,
            quick_search_mode_search,
            quick_search_mode_filter,
            quick_search_ctrl_alt,
            quick_search_alt,
            quick_search_just_char,
            search_window_always_on_top,
            single_instance,
            save_dirs,
            save_tabs,
            save_dir_history,
            save_cmdline_history,
            save_search_history,
        }
    }

    pub fn widget(&self) -> gtk::Widget {
        self.scrolled_window.clone().upcast()
    }

    pub fn read(&self, options: &GeneralOptions) {
        radio_group_set_value(
            [
                (&self.lmb_single_click, LeftMouseButtonMode::SingleClick),
                (&self.lmb_double_click, LeftMouseButtonMode::DoubleClick),
            ],
            options.left_mouse_button_mode.get(),
        );
        self.lmb_unselects
            .set_active(options.left_mouse_button_unselects.get());
        radio_group_set_value(
            [
                (&self.mmb_cd_up, MiddleMouseButtonMode::GoesUpDir),
                (&self.mmb_new_tab, MiddleMouseButtonMode::OpensNewTab),
            ],
            options.middle_mouse_button_mode.get(),
        );
        radio_group_set_value(
            [
                (&self.rmb_popup, RightMouseButtonMode::PopupsMenu),
                (&self.rmb_select, RightMouseButtonMode::Selects),
            ],
            options.right_mouse_button_mode.get(),
        );
        self.delete_to_trash.set_active(options.use_trash.get());
        self.select_dirs.set_active(options.select_dirs.get());
        self.case_sensitive.set_active(options.case_sensitive.get());
        radio_group_set_value(
            [
                (&self.quick_search_mode_search, QuickSearchMode::Search),
                (&self.quick_search_mode_filter, QuickSearchMode::Filter),
            ],
            options.quick_search_default_mode.get(),
        );
        radio_group_set_value(
            [
                (&self.quick_search_ctrl_alt, QuickSearchShortcut::CtrlAlt),
                (&self.quick_search_alt, QuickSearchShortcut::Alt),
                (
                    &self.quick_search_just_char,
                    QuickSearchShortcut::JustACharacter,
                ),
            ],
            options.quick_search_shortcut.get(),
        );
        self.search_window_always_on_top
            .set_active(options.search_window_is_transient.get());
        self.single_instance
            .set_active(!options.allow_multiple_instances.get());
        self.save_dirs.set_active(options.save_dirs_on_exit.get());
        self.save_tabs.set_active(options.save_tabs_on_exit.get());
        self.save_dir_history
            .set_active(options.save_directory_history_on_exit.get());
        self.save_cmdline_history
            .set_active(options.save_command_line_history_on_exit.get());
        self.save_search_history
            .set_active(options.save_search_history.get());
    }

    pub fn write(&self, options: &GeneralOptions) -> WriteResult {
        options.left_mouse_button_mode.set(radio_group_get_value([
            (&self.lmb_single_click, LeftMouseButtonMode::SingleClick),
            (&self.lmb_double_click, LeftMouseButtonMode::DoubleClick),
        ]))?;
        options
            .left_mouse_button_unselects
            .set(self.lmb_unselects.is_active())?;
        options
            .middle_mouse_button_mode
            .set(radio_group_get_value([
                (&self.mmb_cd_up, MiddleMouseButtonMode::GoesUpDir),
                (&self.mmb_new_tab, MiddleMouseButtonMode::OpensNewTab),
            ]))?;
        options.right_mouse_button_mode.set(radio_group_get_value([
            (&self.rmb_popup, RightMouseButtonMode::PopupsMenu),
            (&self.rmb_select, RightMouseButtonMode::Selects),
        ]))?;
        options.use_trash.set(self.delete_to_trash.is_active())?;
        options.select_dirs.set(self.select_dirs.is_active())?;
        options
            .case_sensitive
            .set(self.case_sensitive.is_active())?;
        options
            .quick_search_default_mode
            .set(radio_group_get_value([
                (&self.quick_search_mode_search, QuickSearchMode::Search),
                (&self.quick_search_mode_filter, QuickSearchMode::Filter),
            ]))?;
        options.quick_search_shortcut.set(radio_group_get_value([
            (&self.quick_search_ctrl_alt, QuickSearchShortcut::CtrlAlt),
            (&self.quick_search_alt, QuickSearchShortcut::Alt),
            (
                &self.quick_search_just_char,
                QuickSearchShortcut::JustACharacter,
            ),
        ]))?;
        options
            .search_window_is_transient
            .set(self.search_window_always_on_top.is_active())?;
        options
            .allow_multiple_instances
            .set(!self.single_instance.is_active())?;
        options.save_dirs_on_exit.set(self.save_dirs.is_active())?;
        options.save_tabs_on_exit.set(self.save_tabs.is_active())?;
        options
            .save_directory_history_on_exit
            .set(self.save_dir_history.is_active())?;
        options
            .save_command_line_history_on_exit
            .set(self.save_cmdline_history.is_active())?;
        options
            .save_search_history
            .set(self.save_search_history.is_active())?;
        Ok(())
    }
}
