use std::error::Error;
use std::time::SystemTime;
use lazy_static::lazy_static;
use log::{debug, error, info, warn};
use prometheus::{IntGauge, IntCounter, register_int_counter, register_int_gauge};
use serde::{Deserialize, Serialize};

lazy_static! {
    static ref NEXRAD_LAST_CHUNK_TIME: IntGauge = register_int_gauge!("rtwx_nexrad_last_chunk_time", "Unix timestamp of when the last chunk was received from NEXRAD").unwrap();
    static ref NEXRAD_CHUNKS_RECEIVED: IntCounter = register_int_counter!("rtwx_nexrad_chunks_total", "Total number of chunks received from NEXRAD").unwrap();
}

pub mod firehose;
pub mod archive;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NexradMode {
    Firehose,
    Archive
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    simple_logger::init_with_env()?;

    info!("core's realtime weather API {} starting up", env!("CARGO_PKG_VERSION"));

    info!("initializing primary radar (NOAA NEXRAD) via AWS API");

    let nexrad_mode = std::env::var("RTWX_NEXRAD_MODE").expect("env var RTWX_NEXRAD_MODE is required and must be set to 'archive' (recommended) or 'firehose' (expensive)");
    let nexrad_mode = match nexrad_mode.as_str() {
        "firehose" => NexradMode::Firehose,
        "archive" => NexradMode::Archive,
        _ => {
            error!("env var RTWX_NEXRAD_MODE must be set to 'archive' or 'firehose'");
            std::process::exit(1);
        }
    };
    if nexrad_mode == NexradMode::Firehose {
        warn!("warning: firehose intake mode is *very* expensive ($2-5/day!) to operate");
        warn!("warning: please be careful!");
    }

    let config = aws_config::load_from_env().await;
    let sqs_client = aws_sdk_sqs::Client::new(&config);

    info!("NEXRAD in alignment. May take up to 10 minutes for data to be available worldwide");

    let mut total_frames = 0;
    let start_time = SystemTime::now();

    let queue_url = match nexrad_mode {
        NexradMode::Firehose => firehose::FIREHOSE_SQS_URL,
        NexradMode::Archive => archive::ARCHIVE_SQS_URL
    };

    loop {
        let rcv_message_output = sqs_client.receive_message().max_number_of_messages(10).queue_url(queue_url).send().await?;
        for message in rcv_message_output.messages.unwrap_or_default() {
            // decode frame
            if nexrad_mode == NexradMode::Firehose {
                let notification: firehose::S3Notification = serde_json::from_str(&message.body.unwrap())?;
                let frame: firehose::S3NEXRADData = serde_json::from_str(&notification.message)?;
                total_frames += 1;
                let total_seconds: f64 = (SystemTime::now().duration_since(start_time).unwrap().as_millis() as f64) / 1000f64;
                info!("New NEXRAD frame: {} {} vol {} chunk {} type {} version {} @ {}/{} rate {} frames/second", frame.site_id, frame.date_time, frame.volume_id, frame.chunk_id, frame.chunk_type, frame.l2version, frame.s3bucket, frame.key, (total_frames as f64) / total_seconds);
            } else {
                info!("Archive mode not available yet");
            }
        }
    }


    info!("lightning data not yet available (Blitzortung)");

    Ok(())
}
