use super::*;

pub struct SwitchScreen {
    switch: gtk::Switch,
    switch_screen: gtk::Box,
    disconnected_banner: adw::Banner,
    status_label: gtk::Label,
}

#[derive(Debug, PartialEq, Eq)]
pub enum SwitchScreenMsg {
    Refresh,
    Start,
    Stop,
}

#[relm4::component(pub, async)]
impl AsyncComponent for SwitchScreen {
    type Init = ();
    type Input = SwitchScreenMsg;
    type Output = ();
    type CommandOutput = ();

    view! {
        gtk::Box {
            set_orientation: gtk::Orientation::Vertical,
            set_valign: Align::Fill,

            gtk::Box {
                set_orientation: gtk::Orientation::Vertical,
                set_spacing: 5,
                set_margin_all: 5,
                set_valign: Align::Start,

                #[name(setup_banner)]
                adw::Banner {
                    set_title: "Burrow daemon is not reachable",
                },
            },

            #[name(switch_screen)]
            gtk::Box {
                set_orientation: gtk::Orientation::Vertical,
                set_spacing: 10,
                set_margin_all: 5,
                set_valign: Align::Center,
                set_vexpand: true,

                gtk::Label {
                    set_label: "Burrow Tunnel",
                },

                #[name(status_label)]
                gtk::Label {
                    set_label: "Checking daemon status",
                },

                #[name(switch)]
                gtk::Switch {
                    set_halign: Align::Center,
                    set_hexpand: false,
                    set_vexpand: false,
                    connect_active_notify => move |switch|
                        sender.input(if switch.is_active() { SwitchScreenMsg::Start } else { SwitchScreenMsg::Stop })
                },
            }
        }
    }

    async fn init(
        _: Self::Init,
        root: Self::Root,
        sender: AsyncComponentSender<Self>,
    ) -> AsyncComponentParts<Self> {
        let widgets = view_output!();

        let mut model = SwitchScreen {
            switch: widgets.switch.clone(),
            switch_screen: widgets.switch_screen.clone(),
            disconnected_banner: widgets.setup_banner.clone(),
            status_label: widgets.status_label.clone(),
        };

        model.refresh().await;

        AsyncComponentParts { model, widgets }
    }

    async fn update(
        &mut self,
        msg: Self::Input,
        _sender: AsyncComponentSender<Self>,
        _root: &Self::Root,
    ) {
        match msg {
            SwitchScreenMsg::Refresh => self.refresh().await,
            SwitchScreenMsg::Start => {
                match daemon_api::start_tunnel().await {
                    Ok(()) => self.status_label.set_label("Tunnel running"),
                    Err(error) => self
                        .status_label
                        .set_label(&format!("Start failed: {error}")),
                }
                self.refresh().await;
            }
            SwitchScreenMsg::Stop => {
                match daemon_api::stop_tunnel().await {
                    Ok(()) => self.status_label.set_label("Tunnel stopped"),
                    Err(error) => self
                        .status_label
                        .set_label(&format!("Stop failed: {error}")),
                }
                self.refresh().await;
            }
        }
    }
}

impl SwitchScreen {
    async fn refresh(&mut self) {
        match daemon_api::tunnel_state().await {
            Ok(daemon_api::TunnelState::Running) => {
                self.disconnected_banner.set_revealed(false);
                self.switch_screen.set_sensitive(true);
                self.status_label.set_label("Tunnel running");
                self.switch.set_active(true);
            }
            Ok(daemon_api::TunnelState::Stopped) => {
                self.disconnected_banner.set_revealed(false);
                self.switch_screen.set_sensitive(true);
                self.status_label.set_label("Tunnel stopped");
                self.switch.set_active(false);
            }
            Err(error) => {
                self.disconnected_banner.set_revealed(true);
                self.switch_screen.set_sensitive(false);
                self.status_label
                    .set_label(&format!("Daemon unavailable: {error}"));
                self.switch.set_active(false);
            }
        }
    }
}
