use {
    envmnt::{get_or, get_parse_or, get_u16},
    icann_rdap_srv::{
        config::{
            data_dir, debug_config_vars, JsContactConversion, ListenConfig, ServiceConfig,
            StorageType, AUTO_RELOAD, BOOTSTRAP, JSCONTACT_CONVERSION, LISTEN_ADDR, LISTEN_PORT,
            LOG, UPDATE_ON_BOOTSTRAP,
        },
        error::RdapServerError,
        server::Listener,
    },
    std::{path::Path, str::FromStr},
    tracing_subscriber::{
        fmt, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter,
    },
};

#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<(), RdapServerError> {
    dotenvy::dotenv().ok();
    tracing_subscriber::registry()
        .with(fmt::layer())
        .with(EnvFilter::from_env(LOG))
        .init();

    debug_config_vars();

    let data_dir = data_dir()?;
    let data_path = Path::new(&data_dir);
    if !data_path.is_dir() {
        return Err(RdapServerError::InvalidArg(format!(
            "Data directory {} does not exist or is not a directory.",
            data_path.display()
        )));
    }

    let listen_addr = get_or(LISTEN_ADDR, "127.0.0.1");
    let listen_port = get_u16(LISTEN_PORT, 3000);
    let storage_type = StorageType::new_from_env()?;
    let auto_reload: bool = get_parse_or(AUTO_RELOAD, true)?;
    let bootstrap: bool = get_parse_or(BOOTSTRAP, false)?;
    let update_on_bootstrap: bool = get_parse_or(UPDATE_ON_BOOTSTRAP, false)?;
    let jscontact_conversion =
        JsContactConversion::from_str(&get_or(JSCONTACT_CONVERSION, "none"))?;

    let listener = Listener::listen(
        &ListenConfig::builder()
            .ip_addr(listen_addr)
            .port(listen_port)
            .build(),
    )
    .await?;
    listener
        .start_server(
            &ServiceConfig::builder()
                .storage_type(storage_type)
                .data_dir(data_dir)
                .auto_reload(auto_reload)
                .bootstrap(bootstrap)
                .update_on_bootstrap(update_on_bootstrap)
                .jscontact_conversion(jscontact_conversion)
                .build(),
        )
        .await?;
    Ok(())
}
