use gettextrs::pgettext;
use gtk::{glib, prelude::*, subclass::prelude::*};

use super::{InterPanelMessage, app_window::AppWindow};
use crate::{
    format2,
    systemd::{data::UnitInfo, enums::StartStopMode, errors::SystemdErrors},
    widget::unit_control_panel::enums::UnitContolType,
};
use base::enums::UnitDBusLevel;

mod controls;
pub mod enums;
mod imp;
pub mod side_control_panel;

glib::wrapper! {
    pub struct UnitControlPanel(ObjectSubclass<imp::UnitControlPanelImpl>)
    @extends gtk::Box, gtk::Widget,
    @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}

impl UnitControlPanel {
    pub fn selection_change(&self, unit: Option<&UnitInfo>) {
        self.imp().selection_change(unit);
    }

    pub fn set_app_window(&self, app_window: &AppWindow) {
        self.imp().set_overlay(app_window);
    }

    pub fn app_window(&self) -> Option<AppWindow> {
        self.imp().app_window()
    }

    pub(super) fn add_toast_message(&self, message: &str, use_markup: bool) {
        self.imp().add_toast_message(message, use_markup);
    }

    pub fn display_info_page(&self) {
        self.imp().display_info_page();
    }

    pub fn display_dependencies_page(&self) {
        self.imp().display_dependencies_page();
    }

    pub fn display_journal_page(&self) {
        self.imp().display_journal_page();
    }

    pub fn display_definition_file_page(&self) {
        self.imp().display_definition_file_page();
    }

    pub fn set_inter_message(&self, action: &InterPanelMessage) {
        self.imp().set_inter_message(action);
    }

    pub(super) fn call_method<T>(
        &self,
        method_name: &str,
        need_selected_unit: bool,
        button: &impl IsA<gtk::Widget>,
        systemd_method: impl Fn(Option<(UnitDBusLevel, String)>) -> Result<T, SystemdErrors>
        + std::marker::Send
        + 'static,
        return_handle: impl FnOnce(&str, Option<&UnitInfo>, Result<T, SystemdErrors>, &UnitControlPanel)
        + 'static,
    ) where
        T: Send + 'static,
    {
        self.imp().call_method(
            method_name,
            need_selected_unit,
            button,
            systemd_method,
            return_handle,
        );
    }

    pub fn parent_window(&self) -> gtk::Window {
        self.imp().parent_window()
    }

    pub fn start_restart(
        &self,
        unit_name: &str,
        unit_op: Option<&UnitInfo>,
        start_results: Result<String, SystemdErrors>,
        action: UnitContolType,
        mode: StartStopMode,
    ) {
        self.imp()
            .start_restart(unit_name, unit_op, start_results, action, mode)
    }

    pub(super) fn current_unit(&self) -> Option<UnitInfo> {
        self.imp().current_unit()
    }
}

pub fn work_around_dialog(cmd: &str, err: &SystemdErrors, method: &str, window: &gtk::Window) {
    let content_box = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(15)
        .margin_start(10)
        .margin_end(10)
        .margin_top(15)
        .margin_bottom(15)
        .build();

    content_box.append(
        &gtk::Label::builder()
            .label(format2!(
                // workaround text line
                pgettext(
                    "workaround",
                    "Unfortunately <b>SysD Manager</b> can't perfom <b>{}</b> action."
                ),
                method
            ))
            .use_markup(true)
            .build(),
    );
    content_box.append(
        &gtk::Label::builder()
            .label(
                // workaround text line
                pgettext(
                    "workaround",
                    "The authorisation can be configured in the following file :",
                ),
            )
            .build(),
    );

    let file_path = "/usr/share/dbus-1/system.d/org.freedesktop.systemd1.conf";
    content_box.append(
        &gtk::LinkButton::builder()
            .label(file_path)
            .uri(format!("file://{file_path}"))
            .build(),
    );

    content_box.append(
        &gtk::Label::builder()
            .label(
                // workaround text line
                pgettext(
                    "workaround",
                    "Otherwise, you can try the bellow command line in your terminal",
                ),
            )
            .margin_top(10)
            .build(),
    );

    let label_fallback = gtk::Label::builder()
        .label(cmd)
        .selectable(true)
        .wrap(true)
        .css_classes(["journal_message"])
        .build();

    content_box.append(&label_fallback);

    let tool_bar = adw::ToolbarView::builder().content(&content_box).build();
    tool_bar.add_top_bar(&adw::HeaderBar::new());

    let dialog = adw::Window::builder()
        .title(format2!(
            //workaround dialog title -- "Fail! {SYSTEMD HUMAN ERROR (English)}"
            pgettext("workaround", "Fail! {}"),
            err.human_error_type()
        ))
        .content(&tool_bar)
        .transient_for(window)
        .modal(true)
        .build();

    dialog.present();
}
