use crate::{
    models::{AppState, SharedAppState},
    modules::{api, evok, heat_pump},
    utilities::logger::init_logger,
};
use dotenvy::dotenv;
use lazy_static::lazy_static;
use modules::heat_pump::types::{HPSendingFrame, HeatPumpChannelContent};
use std::{
    env,
    sync::{Arc, Mutex},
};
use tokio::sync::mpsc;

mod models;
mod modules;
mod utilities;

// Initialize application state
lazy_static! {
    pub static ref APP_STATE: SharedAppState = Arc::new(Mutex::new(AppState::new()));
}

#[actix_web::main]
async fn main() -> Result<(), ()> {
    dotenv().ok();

    init_logger();

    // Create a channel for sending messages to the websocket
    let evok_channel = mpsc::channel::<Vec<u8>>(100);
    let evok_tx_clone_api = evok_channel.0.clone();

    // Create a channel for sending messages to trigger heat pump updates
    let heat_pump_channel = mpsc::channel::<HeatPumpChannelContent>(100);
    let heat_pump_tx_clone_api = heat_pump_channel.0.clone();
    let heat_pump_tx_clone_init = heat_pump_channel.0.clone();

    if let Ok(var) = env::var("RUN_EVOK") {
        if var == "true" {
            evok::main::run(evok_channel).await;
        }
    }

    heat_pump::main::run(heat_pump_channel).await;

    // Send initial message to heat pump to start the communication
    tokio::task::spawn(async move {
        heat_pump_tx_clone_init
            .send((HPSendingFrame::First, None))
            .await
            .unwrap();
    });

    api::main::run(evok_tx_clone_api, heat_pump_tx_clone_api).await;

    Ok(())
}
