use super::electric_heating::ElectricHeating;
use serde::{Deserialize, Serialize};

// section.frame.byte

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct HPState {
    /// Is connection with heat pump established and initialized
    pub established_connection: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mode: Option<u8>,
    /// B.1.2 -> The actual frequency is 0 for downtime
    #[serde(skip_serializing_if = "Option::is_none")]
    pub compressor_frequency: Option<u8>,
    /// B.1.5 -> Machine current value
    #[serde(skip_serializing_if = "Option::is_none")]
    pub machine_current_value: Option<u8>,
    /// B.1.6 -> °C
    #[serde(skip_serializing_if = "Option::is_none")]
    pub water_temperature: Option<u8>,
    /// B.1.9 -> °C
    #[serde(skip_serializing_if = "Option::is_none")]
    pub water_tank_temperature: Option<u8>,
    /// B.1.11 -> °C
    #[serde(skip_serializing_if = "Option::is_none")]
    pub water_supply_pipe_temperature: Option<u8>,
    /// B.1.12 ->°C
    #[serde(skip_serializing_if = "Option::is_none")]
    pub solar_collector_temperature: Option<u8>,
    /// B.1.14 -> Outdoor ambient temperature. Transmission value = °C * 2 + 60
    #[serde(skip_serializing_if = "Option::is_none")]
    pub outdoor_ambient_temperature: Option<f32>,
    /// B.2.1 -> Value of the electronic expansion valve opening. Transmission value = number of steps / 2
    #[serde(skip_serializing_if = "Option::is_none")]
    pub electronic_expansion_valve_opening_degree: Option<u8>,
    /// B.2.2 -> Transmission value = °C * 2 + 30
    #[serde(skip_serializing_if = "Option::is_none")]
    pub outdoor_coil_temperature: Option<f32>,
    /// B.2.3 -> Transmission value = °C
    #[serde(skip_serializing_if = "Option::is_none")]
    pub exhaust_gas_temperature: Option<u8>,
    /// B.2.6 -> Transmission value = °C * 2 + 30
    #[serde(skip_serializing_if = "Option::is_none")]
    pub return_air_temperature: Option<f32>,
    /// B.2.7 -> Transmission value = °C * 2 + 30
    #[serde(skip_serializing_if = "Option::is_none")]
    pub throttling_temperature: Option<f32>,
    /// B.1.8 -> Electric heating flag (1 for on, 0 for off)
    pub electric_heating: ElectricHeating,

    pub flags: Flags,
    pub faults: Faults,
}

impl HPState {
    pub fn new() -> Self {
        Self {
            established_connection: false,
            mode: None,
            compressor_frequency: None,
            water_temperature: None,
            water_tank_temperature: None,
            water_supply_pipe_temperature: None,
            solar_collector_temperature: None,
            outdoor_ambient_temperature: None,
            outdoor_coil_temperature: None,
            exhaust_gas_temperature: None,
            return_air_temperature: None,
            throttling_temperature: None,
            machine_current_value: None,
            electronic_expansion_valve_opening_degree: None,
            electric_heating: ElectricHeating::default(),
            flags: Flags::default(),
            faults: Faults::default(),
        }
    }
}
impl Default for HPState {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Faults {
    // B.1.3 -> A value of 0 indicates no fault
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_1: Option<Vec<u8>>,
    // B.1.4 -> A value of 0 indicates no fault
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_2: Option<Vec<u8>>,
    // B.1.13 -> A value of 0 indicates no fault
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_3: Option<Vec<u8>>,
    // B.2.8 -> A value of 0 indicates no fault
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error_4: Option<Vec<u8>>,
}

impl Faults {
    pub fn new() -> Self {
        Self {
            error_1: None,
            error_2: None,
            error_3: None,
            error_4: None,
        }
    }
}
impl Default for Faults {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Flags {
    /// B.1.7 -> 0 means no
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status_1: Option<Vec<u8>>,
    /// B.2.9 ->  0 means no
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status_2: Option<Vec<u8>>,
}

impl Flags {
    pub fn new() -> Self {
        Self {
            status_1: None,
            status_2: None,
        }
    }
}
impl Default for Flags {
    fn default() -> Self {
        Self::new()
    }
}
