#![allow(dead_code)]

use std::net::Ipv4Addr;
use serde::{Deserialize, Serialize};

/// # an Error enum (next will be deleted and replaced)
pub enum CustomError {
    Fatal,
}

#[derive(Debug, PartialEq)]
pub enum ConfigActuality {
    Local,
    Remote,
}

/// # Struct for the 1st level in json conf file
/// ## for storing main config data
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : `TrackingProcess`
/// 
/// ``` json
/// {
/// ->  "dateOfCreation": "1721381809104",
/// ->  "configServer": "localhost",
/// ->  "processes": [
///     { ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Processes {
    // #[serde(rename="id")]
    // runner_id: usize,
    #[serde(rename = "dateOfCreation")]
    pub date_of_creation: String,
    #[serde(rename = "configServer")]
    pub config_server: String,
    #[serde(default)]
    pub processes: Vec<TrackingProcess>,
}

/// # Struct for the 2nd level in json conf file
/// ## for each process to contain info, such as name, path and dependencies
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : `Dependencies`
/// 
/// ``` json
/// ...
///  "processes": [
/// ->    {
/// ->        "name": "temp-process",
/// ->        "path": "/home/user/monitor/runner-rs/temp-process",
/// ->        "dependencies": { ... }
/// -> }, ...
/// ]
/// ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TrackingProcess {
    pub name: String,
    pub path: String,
    pub dependencies: Dependencies,
}

/// # Struct for the 3d level in json conf file
/// ## for processes' dependencies including files and services
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : `Files`, `Services`
/// 
/// ``` json
/// ...
///    "path": "/home/user/monitor/runner-rs/temp-process",
/// -> "dependencies": {
/// ->    "files": [ ... ],
/// ->    "services": [ ... ]
/// ->  }
/// ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Dependencies {
    #[serde(default)]
    pub files: Vec<Files>,
    #[serde(default)]
    pub services: Vec<Services>,
}

/// # Struct for the 4th level in json conf file
/// ## for containing file object with its triggers to manipulate in daemons
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : `FileTriggers`
/// 
/// ``` json
/// ...
/// "files": [
/// ->  {
/// ->    "filename": "dep-file",
/// ->    "src": "/home/user/monitor/runner-rs/tests/examples/",
/// ->    "triggers": { ... }
/// ->  } , 
/// ...
/// ], ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Files {
    pub filename: String,
    pub src: String,
    pub triggers: FileTriggers,
}

/// # Struct for the 4th level in json conf file
/// ## for containing service object with its triggers to manipulate in daemons
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : `ServiceTriggers`
/// 
/// ``` json
/// ...
/// "services": [
/// ->  {
/// ->    "hostname" : "ya.ru",
/// ->    "port" : 443,
/// ->    "triggers": { ... }
/// ->  } , 
/// ...
/// ], ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Services {
    pub hostname: String,
    pub port: u32,
    pub triggers: ServiceTriggers,
}

/// # Struct for the 5th level in json conf file
/// ## for instancing each service's policies such as on lost or time to wait till reachable
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : -
/// 
/// ``` json
/// ...
///    "port": 443,
/// -> "triggers": {
/// ->    "wait": 10,
/// ->    "delay": 2,
/// ->    "onLost": "hold"
/// ->  }
/// ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ServiceTriggers {
    pub wait: u32,
    pub delay: u32,
    #[serde(rename = "onLost")]
    pub on_lost: String,
}

/// # Struct for the 5th level in json conf file
/// ## for instancing each file's policies such as on-delete or onupdate events
/// 
/// > (needed in serialization and deserialization)
/// 
/// *depends on* : -
/// 
/// ``` json
/// ...
///    "src": "/home/user/monitor/runner-rs/tests/examples/",
/// -> "triggers": {
/// ->    "onDelete": "stop",
/// ->    "onChange": "stay"
/// ->  }
/// ...
/// ```
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FileTriggers {
    #[serde(rename = "onDelete")]
    pub on_delete: String,
    #[serde(rename = "onChange")]
    pub on_change: String,
}

/// # Metrics struct
/// ##  for gathering all system metrics (from container + each process)
/// 
/// > (needed in hagent communication, `?...?`)
/// 
/// *depends on* : `ContainerMetrics`, `ProcessMetrics`
/// 
#[derive(Debug, Clone, Serialize,)]
pub struct Metrics {
    pub container_metrics : ContainerMetrics,
    pub processes_metrics : Vec<ProcessMetrics>,
    // pub net_metrics : Vec<PacketInfo>,
}
/// ## Metrics struct's constructor 
impl Metrics {
    pub fn new(cm: ContainerMetrics, prm: Vec<ProcessMetrics>) -> Self {
        Metrics {
            container_metrics : cm,
            processes_metrics : prm,
            // net_metrics : net,
        }
    }
}


/// # Container metrics struct
/// ##  for gathering all container metrics
/// 
/// > (needed in gathering metrics)
/// 
/// *depends on* : -
/// 
#[derive(Debug, Clone, Serialize)]
pub struct ContainerMetrics {
    container_id : String,
    cpu_load : f32,
    ram_load : f32,
    // pub net_activity : ???
    processes : Vec<String>,
}
/// ## Container struct's constructor 
impl ContainerMetrics {
    pub fn new(container_id : &str, cpu: f32, ram: f32, subsystems: Vec<String>,) -> Self{
        ContainerMetrics {
            container_id : String::from(container_id),
            cpu_load  : cpu,
            ram_load  : ram,
            processes : subsystems,
        }
    }
}

/// # Process metrics struct
/// ##  for gathering each process's all metrics
/// 
/// > (needed in gathering metrics)
/// 
/// *depends on* : -
/// 
#[derive(Debug, Clone, Serialize)]
pub struct ProcessMetrics {
    pub process_name : String,
    cpu_load : f32,
    ram_load : f32,
}
/// ## Process struct's constructor 
impl ProcessMetrics {
    pub fn new(process_name :&str, cpu: f32, ram: f32) -> Self {
        ProcessMetrics {
            process_name : String::from(process_name),
            cpu_load : cpu,
            ram_load : ram,
        }
    }
}

/// # Packet info struct
/// ##  for gathering info about container's net activity
/// 
/// > (needed in gathering metrics)
/// 
/// *depends on* : -
/// 
#[derive(Debug, Clone, Serialize)]
pub struct PacketInfo {
    protocol : String,
    dst_ip : Ipv4Addr,
    src_ip : Ipv4Addr,
    size : usize,
}
/// ## PacketInfo's constructor 
impl PacketInfo {
    pub fn new(prt: String, dest: Ipv4Addr, src: Ipv4Addr, size_of_packet: usize) -> Self {
        PacketInfo {
            protocol : prt,
            dst_ip : dest,
            src_ip : src,
            size : size_of_packet,
        }
    }
}