mod dhcp;
mod dns;
mod firewall;
mod http;
mod load_balancer;
mod management;
mod tftp;
use std::sync::Arc;

pub use management::*;
use opnsense_config_xml::Host;
use tokio::sync::RwLock;

use crate::{
    executors::ExecutorError,
    topology::{IpAddress, LogicalHost},
};

#[derive(Debug, Clone)]
pub struct OPNSenseFirewall {
    opnsense_config: Arc<RwLock<opnsense_config::Config>>,
    host: LogicalHost,
}

impl OPNSenseFirewall {
    pub fn get_ip(&self) -> IpAddress {
        self.host.ip
    }

    pub async fn new(host: LogicalHost, port: Option<u16>, username: &str, password: &str) -> Self {
        Self {
            opnsense_config: Arc::new(RwLock::new(
                opnsense_config::Config::from_credentials(host.ip, port, username, password).await,
            )),
            host,
        }
    }

    pub fn get_opnsense_config(&self) -> Arc<RwLock<opnsense_config::Config>> {
        self.opnsense_config.clone()
    }

    async fn commit_config(&self) -> Result<(), ExecutorError> {
        self.opnsense_config
            .read()
            .await
            .apply()
            .await
            .map_err(|e| ExecutorError::UnexpectedError(e.to_string()))
    }
}
