use std::process::Command;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use crossbeam_channel::Sender;
use dbus::arg;
use dbus::blocking::{stdintf::org_freedesktop_dbus::Properties, Connection};
use dbus::Message;
use serde_derive::Deserialize;
use crate::blocks::{Block, ConfigBlock, Update};
use crate::config::SharedConfig;
use crate::errors::*;
use crate::formatting::value::Value;
use crate::formatting::FormatTemplate;
use crate::scheduler::Task;
use crate::util::battery_level_to_icon;
use crate::widgets::text::TextWidget;
use crate::widgets::{I3BarWidget, State};
pub struct KDEConnect {
    id: usize,
    device_id: String,
    device_name: Arc<Mutex<String>>,
    battery_charge: Arc<Mutex<i32>>,
    battery_state: Arc<Mutex<bool>>,
    notif_count: Arc<Mutex<i32>>,
    phone_reachable: Arc<Mutex<bool>>,
    
    
    bat_good: i32,
    bat_info: i32,
    bat_warning: i32,
    bat_critical: i32,
    format: FormatTemplate,
    format_disconnected: FormatTemplate,
    output: TextWidget,
    shared_config: SharedConfig,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields, default)]
pub struct KDEConnectConfig {
    pub device_id: Option<String>,
    
    pub bat_good: i32,
    
    pub bat_info: i32,
    
    pub bat_warning: i32,
    
    pub bat_critical: i32,
    
    pub format: String,
    
    pub format_disconnected: String,
}
impl Default for KDEConnectConfig {
    fn default() -> Self {
        Self {
            device_id: None,
            bat_good: 60,
            bat_info: 60,
            bat_warning: 30,
            bat_critical: 15,
            format: "{name} {bat_icon}{bat_charge} {notif_icon}{notif_count}".to_string(),
            format_disconnected: "{name}".to_string(),
        }
    }
}
impl ConfigBlock for KDEConnect {
    type Config = KDEConnectConfig;
    fn new(
        id: usize,
        block_config: Self::Config,
        shared_config: SharedConfig,
        send: Sender<Task>,
    ) -> Result<Self> {
        let send2 = send.clone();
        let send3 = send.clone();
        let send4 = send.clone();
        let send5 = send.clone();
        let send6 = send.clone();
        let send7 = send.clone();
        let c = Connection::new_session().block_error(
            "kdeconnect",
            &"Failed to establish D-Bus connection".to_string(),
        )?;
        let device_id = if block_config.device_id.is_none() {
            
            let p1 = c.with_proxy(
                "org.kde.kdeconnect",
                "/modules/kdeconnect",
                Duration::from_millis(5000),
            );
            
            let (devices,): (Vec<String>,) = p1
                .method_call("org.kde.kdeconnect.daemon", "devices", (false, true))
                .block_error(
                    "kdeconnect",
                    &"Couldn't connect to KDE Connect daemon".to_string(),
                )?;
            if devices.is_empty() {
                return Err(BlockError(
                    "kdeconnect".to_owned(),
                    "No devices found.".to_owned(),
                ));
            }
            devices[0].clone()
        } else {
            block_config.device_id.unwrap()
        };
        let p2 = c.with_proxy(
            "org.kde.kdeconnect",
            format!("/modules/kdeconnect/devices/{}", device_id),
            Duration::from_millis(5000),
        );
        let initial_name: String = p2
            .get("org.kde.kdeconnect.device", "name")
            .unwrap_or_else(|_| String::from(""));
        let initial_reachable: bool = p2
            .get("org.kde.kdeconnect.device", "isReachable")
            .unwrap_or(false);
        
        
        
        
        
        
        let old_kdeconnect = Command::new("kdeconnect-cli")
            .args(&["--version"])
            .output()
            .block_error(
                "kdeconnect",
                "Failed to check kdeconnect version. Is it installed?",
            )
            .and_then(|raw_output| {
                String::from_utf8(raw_output.stdout)
                    .block_error("kdeconnect", "Failed to check kdeconnect version.")
            })
            .unwrap()
            .contains("kdeconnect-cli 1.");
        let initial_charge = if old_kdeconnect {
            let (charge,): (i32,) = p2
                .method_call("org.kde.kdeconnect.device.battery", "charge", ())
                .unwrap_or((0,));
            charge
        } else {
            let p3 = c.with_proxy(
                "org.kde.kdeconnect",
                format!("/modules/kdeconnect/devices/{}/battery", device_id),
                Duration::from_millis(5000),
            );
            let charge: i32 = p3
                .get("org.kde.kdeconnect.device.battery", "charge")
                .unwrap_or(0);
            charge
        };
        let initial_charging = if old_kdeconnect {
            let (charging,): (bool,) = p2
                .method_call("org.kde.kdeconnect.device.battery", "isCharging", ())
                .unwrap_or((false,));
            charging
        } else {
            let p3 = c.with_proxy(
                "org.kde.kdeconnect",
                format!("/modules/kdeconnect/devices/{}/battery", device_id),
                Duration::from_millis(5000),
            );
            let charging: bool = p3
                .get("org.kde.kdeconnect.device.battery", "isCharging")
                .unwrap_or(false);
            charging
        };
        let initial_notifications = if old_kdeconnect {
            let (notifications,): (Vec<String>,) = p2
                .method_call(
                    "org.kde.kdeconnect.device.notifications",
                    "activeNotifications",
                    (),
                )
                .unwrap_or((vec![String::from("")],));
            notifications
        } else {
            let p4 = c.with_proxy(
                "org.kde.kdeconnect",
                format!("/modules/kdeconnect/devices/{}/notifications", device_id),
                Duration::from_millis(5000),
            );
            let (notifications,): (Vec<String>,) = p4
                .method_call(
                    "org.kde.kdeconnect.device.notifications",
                    "activeNotifications",
                    (),
                )
                .unwrap_or((vec![String::from("")],));
            notifications
        };
        let device_id_copy = device_id.clone();
        let device_name = Arc::new(Mutex::new(initial_name));
        let device_name_copy = device_name.clone();
        let charge = Arc::new(Mutex::new(initial_charge));
        let charge_copy = charge.clone();
        
        #[allow(clippy::mutex_atomic)]
        let charging = Arc::new(Mutex::new(initial_charging));
        let charging_copy = charging.clone();
        let notif_count = Arc::new(Mutex::new(initial_notifications.len() as i32));
        let notif_count_copy1 = notif_count.clone();
        let notif_count_copy2 = notif_count.clone();
        let notif_count_copy3 = notif_count.clone();
        
        #[allow(clippy::mutex_atomic)]
        let reachable = Arc::new(Mutex::new(initial_reachable));
        let reachable_copy1 = reachable.clone();
        let reachable_copy2 = reachable.clone();
        
        
        
        
        
        
        
        
        
        thread::Builder::new()
            .name("kdeconnect".into())
            .spawn(move || {
                let c = Connection::new_session()
                    .expect("Failed to establish D-Bus connection in thread");
                let p1 = c.with_proxy(
                    "org.kde.kdeconnect",
                    format!("/modules/kdeconnect/devices/{}", device_id_copy),
                    Duration::from_millis(5000),
                );
                let _device_name_handler = p1.match_signal(
                    move |s: OrgKdeKdeconnectDeviceNameChanged, _: &Connection, _: &Message| {
                        let mut name = device_name_copy.lock().unwrap();
                        *name = s.name;
                        
                        send2
                            .send(Task {
                                id,
                                update_time: Instant::now(),
                            })
                            .unwrap();
                        true
                    },
                );
                let _phone_reachable_handler = p1.match_signal(
                    move |s: OrgKdeKdeconnectDeviceReachableChanged,
                          _: &Connection,
                          _: &Message| {
                        let mut reachable = reachable_copy1.lock().unwrap();
                        *reachable = s.reachable;
                        
                        
                        
                        
                        
                        
                        send6
                            .send(Task {
                                id,
                                update_time: Instant::now(),
                            })
                            .unwrap();
                        true
                    },
                );
                if old_kdeconnect {
                    let _battery_state_handler = p1.match_signal(
                        move |s: OrgKdeKdeconnectDeviceBatteryStateChanged,
                              _: &Connection,
                              _: &Message| {
                            let mut charging = charging_copy.lock().unwrap();
                            *charging = s.charging;
                            
                            
                            
                            
                            
                            
                            send.send(Task {
                                id,
                                update_time: Instant::now(),
                            })
                            .unwrap();
                            true
                        },
                    );
                    let _battery_charge_handler = p1.match_signal(
                        move |s: OrgKdeKdeconnectDeviceBatteryChargeChanged,
                              _: &Connection,
                              _: &Message| {
                            let mut charge = charge_copy.lock().unwrap();
                            *charge = s.charge;
                            true
                        },
                    );
                } else {
                    let p2 = c.with_proxy(
                        "org.kde.kdeconnect",
                        format!("/modules/kdeconnect/devices/{}/battery", device_id_copy),
                        Duration::from_millis(5000),
                    );
                    let _battery_state_handler = p2.match_signal(
                        move |s: OrgKdeKdeconnectDeviceBatteryRefreshed,
                              _: &Connection,
                              _: &Message| {
                            let mut charging = charging_copy.lock().unwrap();
                            *charging = s.is_charging;
                            let mut charge = charge_copy.lock().unwrap();
                            *charge = s.charge;
                            send.send(Task {
                                id,
                                update_time: Instant::now(),
                            })
                            .unwrap();
                            true
                        },
                    );
                };
                if old_kdeconnect {
                    let _notification_added_handler = p1.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsNotificationPosted,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy1.lock().unwrap();
                            *notif_count += 1;
                            
                            send3
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                    let _notification_removed_handler = p1.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsNotificationRemoved,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy2.lock().unwrap();
                            *notif_count = if *notif_count - 1 < 0 {
                                0
                            } else {
                                *notif_count - 1
                            };
                            
                            send4
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                    let _notification_all_removed_handler = p1.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy3.lock().unwrap();
                            *notif_count = 0;
                            
                            send5
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                } else {
                    let p3 = c.with_proxy(
                        "org.kde.kdeconnect",
                        format!(
                            "/modules/kdeconnect/devices/{}/notifications",
                            device_id_copy
                        ),
                        Duration::from_millis(5000),
                    );
                    let _notification_added_handler = p3.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsNotificationPosted,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy1.lock().unwrap();
                            *notif_count += 1;
                            
                            send3
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                    let _notification_removed_handler = p3.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsNotificationRemoved,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy2.lock().unwrap();
                            *notif_count = if *notif_count - 1 < 0 {
                                0
                            } else {
                                *notif_count - 1
                            };
                            
                            send4
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                    let _notification_all_removed_handler = p3.match_signal(
                        move |_s: OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved,
                              _: &Connection,
                              _: &Message| {
                            let mut notif_count = notif_count_copy3.lock().unwrap();
                            *notif_count = 0;
                            
                            send5
                                .send(Task {
                                    id,
                                    update_time: Instant::now(),
                                })
                                .unwrap();
                            true
                        },
                    );
                    
                    
                };
                let p4 = c.with_proxy(
                    "org.kde.kdeconnect",
                    "/modules/kdeconnect",
                    Duration::from_millis(5000),
                );
                let _phone_visible_handler = p4.match_signal(
                    move |s: OrgKdeKdeconnectDaemonDeviceVisibilityChanged,
                          _: &Connection,
                          _: &Message| {
                        
                        let mut reachable = reachable_copy2.lock().unwrap();
                        *reachable = s.is_visible;
                        
                        send7
                            .send(Task {
                                id,
                                update_time: Instant::now(),
                            })
                            .unwrap();
                        true
                    },
                );
                loop {
                    c.process(Duration::from_millis(1000)).unwrap();
                }
            })
            .unwrap();
        Ok(KDEConnect {
            id,
            device_id,
            device_name,
            battery_charge: charge,
            battery_state: charging,
            notif_count,
            
            
            phone_reachable: reachable,
            bat_good: block_config.bat_good,
            bat_info: block_config.bat_info,
            bat_warning: block_config.bat_warning,
            bat_critical: block_config.bat_critical,
            format: FormatTemplate::from_string(&block_config.format)?,
            format_disconnected: FormatTemplate::from_string(&block_config.format_disconnected)?,
            output: TextWidget::new(id, 0, shared_config.clone()).with_icon("phone")?,
            shared_config,
        })
    }
}
impl Block for KDEConnect {
    fn id(&self) -> usize {
        self.id
    }
    fn update(&mut self) -> Result<Option<Update>> {
        let charge = (*self
            .battery_charge
            .lock()
            .block_error("kdeconnect", "failed to acquire lock for `charge`")?)
            as i32;
        let charging = *self
            .battery_state
            .lock()
            .block_error("kdeconnect", "failed to acquire lock for `battery_state`")?;
        let notif_count = *self
            .notif_count
            .lock()
            .block_error("kdeconnect", "failed to acquire lock for `notif_count`")?;
        
        
        
        
        
        
        let phone_reachable = *self
            .phone_reachable
            .lock()
            .block_error("kdeconnect", "failed to acquire lock for `phone_reachable`")?;
        let name = (*self
            .device_name
            .lock()
            .block_error("kdeconnect", "failed to acquire lock for `name`")?)
        .clone();
        let bat_icon = self
            .shared_config
            .get_icon(if charging {
                
                "bat_charging"
            } else if charge < 0 {
                
                "bat_full"
            } else {
                battery_level_to_icon(Ok(charge as u64))
            })
            .unwrap_or_default();
        let values = map!(
            "bat_icon" => Value::from_string(bat_icon.trim().to_string()),
            "bat_charge" => Value::from_integer(charge.clamp(0,100) as i64).percents(),
            "bat_state" => Value::from_string(charging.to_string()),
            "notif_icon" => Value::from_string(self.shared_config.get_icon("notification").unwrap_or_default().trim().to_string()),
            "notif_count" => Value::from_integer(notif_count as i64),
            
            
            "name" => Value::from_string(name),
            "id" => Value::from_string(self.device_id.to_string()) 
        );
        if (
            self.bat_critical,
            self.bat_warning,
            self.bat_info,
            self.bat_good,
        ) == (0, 0, 0, 0)
        {
            self.output.set_state(match notif_count {
                0 => State::Idle,
                _ => State::Info,
            })
        } else if charging {
            self.output.set_state(State::Good);
        } else {
            self.output.set_state(if charge <= self.bat_critical {
                State::Critical
            } else if charge <= self.bat_warning {
                State::Warning
            } else if charge <= self.bat_info {
                State::Info
            } else if charge > self.bat_good {
                State::Good
            } else {
                State::Idle
            });
        }
        if !phone_reachable {
            self.output.set_state(State::Critical);
            self.output.set_icon("phone_disconnected")?;
            self.output
                .set_text(self.format_disconnected.render(&values)?);
        } else {
            self.output.set_icon("phone")?;
            self.output.set_text(self.format.render(&values)?);
        }
        Ok(None)
    }
    
    fn view(&self) -> Vec<&dyn I3BarWidget> {
        vec![&self.output]
    }
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceBatteryRefreshed {
    pub is_charging: bool,
    pub charge: i32,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceBatteryRefreshed {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.is_charging, i);
        arg::RefArg::append(&self.charge, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceBatteryRefreshed {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceBatteryRefreshed {
            is_charging: i.read()?,
            charge: i.read()?,
        })
    }
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceNotificationsNotificationPosted {
    pub public_id: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceNotificationsNotificationPosted {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.public_id, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceNotificationsNotificationPosted {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceNotificationsNotificationPosted {
            public_id: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceNotificationsNotificationPosted {
    const NAME: &'static str = "notificationPosted";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.notifications";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceNotificationsNotificationRemoved {
    pub public_id: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceNotificationsNotificationRemoved {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.public_id, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceNotificationsNotificationRemoved {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceNotificationsNotificationRemoved {
            public_id: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceNotificationsNotificationRemoved {
    const NAME: &'static str = "notificationRemoved";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.notifications";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceNotificationsNotificationUpdated {
    pub public_id: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceNotificationsNotificationUpdated {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.public_id, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceNotificationsNotificationUpdated {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceNotificationsNotificationUpdated {
            public_id: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceNotificationsNotificationUpdated {
    const NAME: &'static str = "notificationUpdated";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.notifications";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved {}
impl arg::AppendAll for OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved {
    fn append(&self, _: &mut arg::IterAppend) {}
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved {
    fn read(_: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved {})
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceNotificationsAllNotificationsRemoved {
    const NAME: &'static str = "allNotificationsRemoved";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.notifications";
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceBatteryRefreshed {
    const NAME: &'static str = "refreshed";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.battery";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceNameChanged {
    pub name: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceNameChanged {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.name, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceNameChanged {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceNameChanged { name: i.read()? })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceNameChanged {
    const NAME: &'static str = "nameChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceReachableChanged {
    pub reachable: bool,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceReachableChanged {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.reachable, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceReachableChanged {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceReachableChanged {
            reachable: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceReachableChanged {
    const NAME: &'static str = "reachableChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDaemonDeviceAdded {
    pub id: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDaemonDeviceAdded {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.id, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDaemonDeviceAdded {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDaemonDeviceAdded { id: i.read()? })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDaemonDeviceAdded {
    const NAME: &'static str = "deviceAdded";
    const INTERFACE: &'static str = "org.kde.kdeconnect.daemon";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDaemonDeviceRemoved {
    pub id: String,
}
impl arg::AppendAll for OrgKdeKdeconnectDaemonDeviceRemoved {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.id, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDaemonDeviceRemoved {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDaemonDeviceRemoved { id: i.read()? })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDaemonDeviceRemoved {
    const NAME: &'static str = "deviceRemoved";
    const INTERFACE: &'static str = "org.kde.kdeconnect.daemon";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDaemonDeviceVisibilityChanged {
    pub id: String,
    pub is_visible: bool,
}
impl arg::AppendAll for OrgKdeKdeconnectDaemonDeviceVisibilityChanged {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.id, i);
        arg::RefArg::append(&self.is_visible, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDaemonDeviceVisibilityChanged {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDaemonDeviceVisibilityChanged {
            id: i.read()?,
            is_visible: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDaemonDeviceVisibilityChanged {
    const NAME: &'static str = "deviceVisibilityChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.daemon";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDaemonDeviceListChanged {}
impl arg::AppendAll for OrgKdeKdeconnectDaemonDeviceListChanged {
    fn append(&self, _: &mut arg::IterAppend) {}
}
impl arg::ReadAll for OrgKdeKdeconnectDaemonDeviceListChanged {
    fn read(_: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDaemonDeviceListChanged {})
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDaemonDeviceListChanged {
    const NAME: &'static str = "deviceListChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.daemon";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceBatteryStateChanged {
    pub charging: bool,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceBatteryStateChanged {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.charging, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceBatteryStateChanged {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceBatteryStateChanged {
            charging: i.read()?,
        })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceBatteryStateChanged {
    const NAME: &'static str = "stateChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.battery";
}
#[derive(Debug)]
pub struct OrgKdeKdeconnectDeviceBatteryChargeChanged {
    pub charge: i32,
}
impl arg::AppendAll for OrgKdeKdeconnectDeviceBatteryChargeChanged {
    fn append(&self, i: &mut arg::IterAppend) {
        arg::RefArg::append(&self.charge, i);
    }
}
impl arg::ReadAll for OrgKdeKdeconnectDeviceBatteryChargeChanged {
    fn read(i: &mut arg::Iter) -> std::result::Result<Self, arg::TypeMismatchError> {
        Ok(OrgKdeKdeconnectDeviceBatteryChargeChanged { charge: i.read()? })
    }
}
impl dbus::message::SignalArgs for OrgKdeKdeconnectDeviceBatteryChargeChanged {
    const NAME: &'static str = "chargeChanged";
    const INTERFACE: &'static str = "org.kde.kdeconnect.device.battery";
}