use std::cell::Cell;

use glib::object::ObjectExt;
use glib::subclass::prelude::{ObjectSubclass, *};
use glib::Properties;
use transmission_client::SessionStats;

use crate::TrSessionStatsDetails;

mod imp {
    use super::*;

    #[derive(Debug, Default, Properties)]
    #[properties(wrapper_type = super::TrSessionStats)]
    pub struct TrSessionStats {
        #[property(get, minimum = 1, default_value = 1)]
        pub torrent_count: Cell<i32>,
        #[property(get, minimum = 1, default_value = 1)]
        pub active_torrent_count: Cell<i32>,
        #[property(get, minimum = 1, default_value = 1)]
        pub paused_torrent_count: Cell<i32>,
        #[property(get, minimum = 1, default_value = 1)]
        pub downloaded_torrent_count: Cell<i32>,
        #[property(get, minimum = 1, default_value = 1)]
        pub download_speed: Cell<i32>,
        #[property(get, minimum = 1, default_value = 1)]
        pub upload_speed: Cell<i32>,

        #[property(get)]
        pub cumulative_stats: TrSessionStatsDetails,
        #[property(get)]
        pub current_stats: TrSessionStatsDetails,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for TrSessionStats {
        const NAME: &'static str = "TrSessionStats";
        type ParentType = glib::Object;
        type Type = super::TrSessionStats;
    }

    #[glib::derived_properties]
    impl ObjectImpl for TrSessionStats {}
}

glib::wrapper! {
    pub struct TrSessionStats(ObjectSubclass<imp::TrSessionStats>);
}

impl TrSessionStats {
    pub(crate) fn refresh_values(&self, rpc_stats: SessionStats, download_count: i32) {
        let imp = self.imp();

        // torrent_count
        if imp.torrent_count.get() != rpc_stats.torrent_count {
            imp.torrent_count.set(rpc_stats.torrent_count);
            self.notify_torrent_count();
        }

        // active_torrent_count
        if imp.active_torrent_count.get() != rpc_stats.active_torrent_count {
            imp.active_torrent_count.set(rpc_stats.active_torrent_count);
            self.notify_active_torrent_count();
        }

        // paused_torrent_count
        if imp.paused_torrent_count.get() != rpc_stats.paused_torrent_count {
            imp.paused_torrent_count.set(rpc_stats.paused_torrent_count);
            self.notify_paused_torrent_count();
        }

        // downloaded_torrent_count
        if imp.downloaded_torrent_count.get() != download_count {
            imp.downloaded_torrent_count.set(download_count);
            self.notify_downloaded_torrent_count();
        }

        // download_speed
        if imp.download_speed.get() != rpc_stats.download_speed {
            imp.download_speed.set(rpc_stats.download_speed);
            self.notify_download_speed();
        }

        // upload_speed
        if imp.upload_speed.get() != rpc_stats.upload_speed {
            imp.upload_speed.set(rpc_stats.upload_speed);
            self.notify_upload_speed();
        }

        imp.cumulative_stats
            .refresh_values(rpc_stats.cumulative_stats);
        imp.current_stats.refresh_values(rpc_stats.current_stats);
    }
}

impl Default for TrSessionStats {
    fn default() -> Self {
        glib::Object::new()
    }
}
