use crate::browser::DeviceBrowser;
use crate::category::DeviceCategory;
use crate::fingerprint::DeviceFingerprint;
use crate::language::DeviceLanguage;
use crate::manufacturer::DeviceManufacturer;
use crate::model::DeviceModel;
use crate::os::DeviceOs;
use crate::platform::DevicePlatform;
use crate::provider::DeviceProvider;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Device {
    pub fingerprint: DeviceFingerprint,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub provider: Option<DeviceProvider>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub category: Option<DeviceCategory>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub model: Option<DeviceModel>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub platform: Option<DevicePlatform>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub manufacturer: Option<DeviceManufacturer>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub os: Option<DeviceOs>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub browser: Option<DeviceBrowser>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub language: Option<DeviceLanguage>,
}

impl Device {
    pub fn new(fingerprint: DeviceFingerprint) -> Self {
        Self {
            fingerprint,
            provider: None,
            category: None,
            model: None,
            platform: None,
            manufacturer: None,
            os: None,
            browser: None,
            language: None,
        }
    }
}

pub struct DeviceBuilder {
    device: Device,
}

impl DeviceBuilder {
    pub fn fingerprint(mut self, fingerprint: DeviceFingerprint) -> Self {
        self.device.fingerprint = fingerprint;
        self
    }

    pub fn provider(mut self, provider: DeviceProvider) -> Self {
        self.device.provider = Some(provider);
        self
    }

    pub fn category(mut self, category: DeviceCategory) -> Self {
        self.device.category = Some(category);
        self
    }

    pub fn model(mut self, model: DeviceModel) -> Self {
        self.device.model = Some(model);
        self
    }

    pub fn platform(mut self, platform: DevicePlatform) -> Self {
        self.device.platform = Some(platform);
        self
    }

    pub fn manufacturer(mut self, manufacturer: DeviceManufacturer) -> Self {
        self.device.manufacturer = Some(manufacturer);
        self
    }

    pub fn os(mut self, os: DeviceOs) -> Self {
        self.device.os = Some(os);
        self
    }

    pub fn browser(mut self, browser: DeviceBrowser) -> Self {
        self.device.browser = Some(browser);
        self
    }

    pub fn language(mut self, language: DeviceLanguage) -> Self {
        self.device.language = Some(language);
        self
    }

    pub fn build(self) -> Device {
        self.device
    }
}
