use log::info;
use entity::gateway::postgres::PostgresGateway;
use elseware::ship::ship::ShipServerStateBuilder;
use networking::interserver::AuthToken;
use drops::{DropTable, StandardDropTable};

fn main() {
    let colors = fern::colors::ColoredLevelConfig::new()
        .error(fern::colors::Color::Red)
        .warn(fern::colors::Color::Yellow)
        .info(fern::colors::Color::Green)
        .debug(fern::colors::Color::White)
        .trace(fern::colors::Color::BrightBlack);
    let stdio = fern::Dispatch::new()
        .level(log::LevelFilter::Debug)
        .format(move |out, message, record| {
            out.finish(format_args!(
                "\x1B[{}m[{}][{}][{}] {}\x1B[0m",
                colors.get_color(&record.level()).to_fg_str(),
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.target(),
                record.level(),
                message,
            ))
        })
        .chain(std::io::stdout());
    fern::Dispatch::new()
        .chain(stdio)
        .apply().unwrap();

    let db_host = std::env::var("DB_HOST").unwrap();
    let db_username = std::env::var("DB_USERNAME").unwrap();
    let db_password = std::env::var("DB_PASSWORD").unwrap();
    let db_dbname = std::env::var("DB_DBNAME").unwrap();
    let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password);

    let shipgate_token = std::env::var("SHIPGATE_TOKEN").unwrap();
    let ship_name = std::env::var("SHIP_NAME").unwrap().parse().unwrap();
    let ip = std::env::var("SELF_IP").unwrap().parse().unwrap();

    let ship_state = ShipServerStateBuilder::default()
        .name(ship_name)
        .ip(ip)
        .port(elseware::ship::ship::SHIP_PORT)
        .gateway(entity_gateway)
        .auth_token(AuthToken(shipgate_token))
        .standard_quest_builder(Box::new(quests::load_standard_quests))
        .government_quest_builder(Box::new(quests::load_government_quests))
        .drop_table_builder(Box::new(StandardDropTable::new))
        .build();

    let shipgate_ip = std::env::var("SHIPGATE_IP").unwrap().parse().unwrap();

    let sub_ship_state = ship_state.clone();
    let ship_loop = async_std::task::spawn(async move {
        networking::mainloop::run_server(sub_ship_state, elseware::ship::ship::SHIP_PORT).await;
    });
    let inter_ship_loop = async_std::task::spawn(async move {
        networking::mainloop::run_interserver_connect(ship_state, shipgate_ip, elseware::login::login::COMMUNICATION_PORT).await;
    });

    info!("[auth/character] starting server");
    async_std::task::block_on(async move {
        futures::future::join_all(vec![ship_loop, inter_ship_loop]).await;
    });
}