/*
    Copyright: 2020 Rasmus Thomsen <oss@cogitri.dev>
    SPDX-License-Identifier: GPL-3.0-or-later
*/

#![deny(clippy::all)]
#![allow(clippy::new_without_default)]
#![warn(clippy::await_holding_refcell_ref)]
#![warn(clippy::cast_lossless)]
#![warn(clippy::comparison_to_empty)]
#![warn(clippy::manual_find_map)]
#![warn(clippy::map_unwrap_or)]
#![warn(clippy::struct_excessive_bools)]
#![warn(clippy::unnecessary_unwrap)]
#![warn(clippy::trivially_copy_pass_by_ref)]
#![allow(clippy::must_use_candidate)]

use crate::dbus_server::DBusServer;
use gettextrs::{TextDomain, TextDomainError};
use log::{debug, error, info, warn, LevelFilter};
use std::{error::Error, future::pending};
use zbus::ConnectionBuilder;

mod apk_package_partial;
mod dbus_server;
mod details_flags;
mod error;

fn setup_logger() -> Result<(), fern::InitError> {
    let syslog_formatter = syslog::Formatter3164 {
        facility: syslog::Facility::LOG_DAEMON,
        hostname: None,
        process: "apk-polkit-server".into(),
        pid: std::process::id(),
    };

    let fern_builder = fern::Dispatch::new().chain(
        // console config
        fern::Dispatch::new()
            .format(move |out, message, record| {
                out.finish(format_args!("[{}] {}", record.level(), message));
            })
            .chain(std::io::stdout()),
    );

    match syslog::unix(syslog_formatter) {
        Ok(syslogger) => {
            fern_builder
                .chain(
                    // syslog config
                    fern::Dispatch::new()
                        .level(LevelFilter::Info)
                        .chain(syslogger),
                )
                .apply()?;
        }
        Err(e) => {
            fern_builder.apply()?;
            error!("Failed to connect to syslog due to error {}!", e);
        }
    }
    Ok(())
}

fn setup_gettext() {
    match TextDomain::new("apk-polkit-rs").init() {
        Ok(locale) => debug!(
            "Found translation; enabling localisation with locale {:?}",
            locale
        ),
        Err(TextDomainError::InvalidLocale(e)) => {
            warn!("Couldn't enable localisation, invalid locale {}", e);
        }
        Err(TextDomainError::TranslationNotFound(e)) => warn!(
            "Couldn't enable localisation, no translation found for locale {}",
            e
        ),
        Err(
            TextDomainError::TextDomainCallFailed(e)
            | TextDomainError::BindTextDomainCallFailed(e)
            | TextDomainError::BindTextDomainCodesetCallFailed(e),
        ) => {
            warn!("Initialising gettext failed! {:?}", e);
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    setup_logger()?;
    setup_gettext();
    info!("Starting server...");

    let _con = ConnectionBuilder::system()?
        .name("dev.Cogitri.apkPolkit2")?
        .serve_at("/dev/Cogitri/apkPolkit2", DBusServer::default())?
        .build()
        .await?;

    pending::<()>().await;

    Ok(())
}
