use std::collections::HashSet;

use super::TransportConfig;
use crate::identity::SharedIdentity;

/// Ditto transport parameters / status
#[derive(Clone)]
pub(crate) struct SyncState {
    sync_active: bool,
    x509_valid: bool,
    web_valid: bool,
    identity: SharedIdentity,
    transport_config: TransportConfig,
}

impl SyncState {
    pub fn new(transport_config: TransportConfig, identity: SharedIdentity) -> SyncState {
        SyncState {
            sync_active: false,
            web_valid: identity.is_web_valid(),
            x509_valid: identity.is_x509_valid(),
            identity,
            transport_config,
        }
    }

    pub fn config(&self) -> &TransportConfig {
        &self.transport_config
    }

    pub fn set_config(&mut self, config: TransportConfig) -> &mut SyncState {
        self.transport_config = config;
        self
    }

    pub fn set_sync(&mut self, activated: bool) -> &mut SyncState {
        self.sync_active = activated;
        self
    }

    pub fn set_x509_valid(&mut self, valid: bool) -> &mut SyncState {
        self.x509_valid = valid;
        self
    }

    pub fn set_web_valid(&mut self, valid: bool) -> &mut SyncState {
        self.web_valid = valid;
        self
    }

    /// Compute effective state using Identity + other field + transport config
    pub fn compute_effective_state(&self) -> Self {
        let mut patched_config = self.transport_config.clone();
        if !self.sync_active || !self.x509_valid {
            patched_config.peer_to_peer.bluetooth_le.enabled = false;
            patched_config.peer_to_peer.lan.enabled = false;
            patched_config.listen.tcp.enabled = false;
            patched_config.connect.tcp_servers = HashSet::new();
        }

        if !self.sync_active || !self.web_valid {
            patched_config.connect.websocket_urls = HashSet::new();
        }

        if !self.sync_active {
            patched_config.listen.http.enabled = false;
        }

        if self.identity.is_cloud_sync_enabled() && self.sync_active && self.web_valid {
            let cloud_url = self
                .identity
                .sync_url()
                .expect("No cloud URL was provided in the Identity");
            patched_config.connect.websocket_urls.insert(cloud_url);
        }
        if patched_config.peer_to_peer.lan.enabled && !patched_config.listen.tcp.enabled {
            patched_config.listen.tcp.enabled = true;
            patched_config.listen.tcp.interface_ip = String::from("[::]");
            patched_config.listen.tcp.port = 0;
        }
        Self {
            transport_config: patched_config,
            ..self.clone()
        }
    }
}
