Skip to content
#[derive(Clone)]
pub struct Server {
    address: (String, u16),
    log_level: String,
    db_path: String,
    reset_db: bool,
    username: String,
    password: String,
}

impl Server {
    pub fn new(
        address: (String, u16),
        log_level: String,
        db_path: String,
        reset_db: bool,
        username: String,
        password: String,
    ) -> Self {
        Server {
            address,
            log_level,
            db_path,
            reset_db,
            username,
            password,
        }
    }

    pub fn address(&self) -> (String, u16) {
        self.address.clone()
    }

    pub fn log_level(&self) -> &str {
        &self.log_level
    }

    pub fn db_path(&self) -> &str {
        &self.db_path
    }

    pub fn maybe_reset_database(&self) {
        if !self.reset_db {
            return;
        }

        log::warn!(
            "RESET_DB is set to true, deleting database file: {}",
            self.db_path
        );

        if std::path::Path::new(&self.db_path).exists() {
            if let Err(e) = std::fs::remove_file(&self.db_path) {
                log::error!("Failed to delete database file: {e}");
            } else {
                log::info!("Database file deleted successfully");
            }
        }
    }

    pub fn username(&self) -> &str {
        &self.username
    }

    pub fn password(&self) -> &str {
        &self.password
    }
}

impl std::fmt::Display for Server {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", ascii(self))
    }
}

pub fn from_env() -> Server {
    let port = std::env::var("PORT")
        .unwrap_or_else(|_| "8080".to_string())
        .parse()
        .unwrap_or(8080);
    let log_level = std::env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string());
    let db_path = std::env::var("DB_PATH").unwrap_or_else(|_| "notes.db".to_string());
    let reset_db = std::env::var("RESET_DB").unwrap_or_default() == "true";
    let username = std::env::var("USERNAME").unwrap_or_else(|_| "admin".to_string());
    let password = std::env::var("PASSWORD").unwrap_or_else(|_| "admin".to_string());

    Server::new(
        ("0.0.0.0".to_string(), port),
        log_level,
        db_path,
        reset_db,
        username,
        password,
    )
}

fn ascii(server: &Server) -> String {
    let (_, port) = server.address();
    let url = format!("http://localhost:{port}");
    let version = env!("CARGO_PKG_VERSION");
    format!("Later v{version}\nServer running at: {url}")
}