// 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::{apps_widget::FavoriteApps, common::create_category};
use crate::options::{GeneralOptions, ProgramsOptions, types::WriteResult};
use gettextrs::gettext;
use gtk::prelude::*;

pub struct ProgramsTab {
    scrolled_window: gtk::ScrolledWindow,
    honor_expect_uris: gtk::CheckButton,
    viewer: gtk::Entry,
    use_internal_viewer: gtk::CheckButton,
    editor: gtk::Entry,
    differ: gtk::Entry,
    search: gtk::Entry,
    use_internal_search: gtk::CheckButton,
    send_to: gtk::Entry,
    termopen: gtk::Entry,
    fav_apps: FavoriteApps,
    termexec: gtk::Entry,
}

impl ProgramsTab {
    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 honor_expect_uris = gtk::CheckButton::builder()
            .label(gettext(
                "Always download remote files before opening in external programs",
            ))
            .build();
        vbox.append(&create_category(
            &gettext("MIME applications"),
            &honor_expect_uris,
        ));

        let grid = gtk::Grid::builder()
            .column_spacing(12)
            .row_spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Standard programs"), &grid));

        let viewer = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Viewer:"))
            .mnemonic_widget(&viewer)
            .build();
        grid.attach(&label, 0, 0, 1, 1);
        grid.attach(&viewer, 1, 0, 1, 1);
        let use_internal_viewer = gtk::CheckButton::builder()
            .label(gettext("Use Internal Viewer"))
            .build();
        grid.attach(&use_internal_viewer, 1, 1, 1, 1);

        let editor = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Editor:"))
            .mnemonic_widget(&editor)
            .build();
        grid.attach(&label, 0, 2, 1, 1);
        grid.attach(&editor, 1, 2, 1, 1);

        let differ = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Differ:"))
            .mnemonic_widget(&differ)
            .build();
        grid.attach(&label, 0, 3, 1, 1);
        grid.attach(&differ, 1, 3, 1, 1);

        let search = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Search:"))
            .mnemonic_widget(&search)
            .build();
        grid.attach(&label, 0, 4, 1, 1);
        grid.attach(&search, 1, 4, 1, 1);
        let use_internal_search = gtk::CheckButton::builder()
            .label(gettext("Use Internal Search"))
            .build();
        grid.attach(&use_internal_search, 1, 5, 1, 1);

        let send_to = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Send files:"))
            .mnemonic_widget(&send_to)
            .build();
        grid.attach(&label, 0, 6, 1, 1);
        grid.attach(&send_to, 1, 6, 1, 1);

        let termopen = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Terminal:"))
            .mnemonic_widget(&termopen)
            .build();
        grid.attach(&label, 0, 7, 1, 1);
        grid.attach(&termopen, 1, 7, 1, 1);

        let fav_apps = FavoriteApps::new();
        vbox.append(&create_category(
            &gettext("Other favourite apps"),
            &fav_apps.widget(),
        ));

        let grid = gtk::Grid::builder()
            .column_spacing(12)
            .row_spacing(6)
            .build();
        vbox.append(&create_category(&gettext("Global app options"), &grid));

        let termexec = gtk::Entry::builder().hexpand(true).build();
        let label = gtk::Label::builder()
            .label(gettext("Terminal command for apps in the list above:"))
            .mnemonic_widget(&termexec)
            .build();
        grid.attach(&label, 0, 0, 1, 1);
        grid.attach(&termexec, 1, 0, 1, 1);

        Self {
            scrolled_window,
            honor_expect_uris,
            viewer,
            use_internal_viewer,
            editor,
            differ,
            search,
            use_internal_search,
            send_to,
            termopen,
            fav_apps,
            termexec,
        }
    }

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

    pub fn read(&self, general_options: &GeneralOptions, programs_options: &ProgramsOptions) {
        self.honor_expect_uris
            .set_active(!programs_options.dont_download.get());
        self.viewer.set_text(&programs_options.viewer_cmd.get());
        self.use_internal_viewer
            .set_active(programs_options.use_internal_viewer.get());
        self.editor.set_text(&programs_options.editor_cmd.get());
        self.differ.set_text(&programs_options.differ_cmd.get());
        self.search.set_text(&programs_options.search_cmd.get());
        self.use_internal_search
            .set_active(programs_options.use_internal_search.get());
        self.send_to.set_text(&programs_options.sendto_cmd.get());
        self.termopen.set_text(&programs_options.terminal_cmd.get());
        self.fav_apps.read(general_options);
        self.termexec
            .set_text(&programs_options.terminal_exec_cmd.get());
    }

    pub fn write(
        &self,
        general_options: &GeneralOptions,
        programs_options: &ProgramsOptions,
    ) -> WriteResult {
        programs_options
            .dont_download
            .set(!self.honor_expect_uris.is_active())?;
        programs_options.viewer_cmd.set(self.viewer.text())?;
        programs_options
            .use_internal_viewer
            .set(self.use_internal_viewer.is_active())?;
        programs_options.editor_cmd.set(self.editor.text())?;
        programs_options.differ_cmd.set(self.differ.text())?;
        programs_options.search_cmd.set(self.search.text())?;
        programs_options
            .use_internal_search
            .set(self.use_internal_search.is_active())?;
        programs_options.sendto_cmd.set(self.send_to.text())?;
        programs_options.terminal_cmd.set(self.termopen.text())?;
        self.fav_apps.write(general_options)?;
        programs_options
            .terminal_exec_cmd
            .set(self.termexec.text())?;
        Ok(())
    }
}
