/*-------------------------------------------------------------------------
 * Copyright (c) Microsoft Corporation.  All rights reserved.
 *
 * documentdb_gateway_core/src/configuration/mod.rs
 *
 *-------------------------------------------------------------------------
 */

mod certs;
mod dynamic;
mod pg_configuration;
mod setup;
mod version;

pub use certs::{CertInputType, CertificateOptions};
pub use dynamic::DynamicConfiguration;
pub use pg_configuration::PgConfiguration;
pub use setup::{env_keys, DocumentDBSetupConfiguration};
pub use version::Version;

use dyn_clone::{clone_trait_object, DynClone};
use std::fmt::Debug;

use crate::telemetry::config::TelemetryOptions;

pub(crate) const SOCKET_CONNECTION_IDLE_TIMEOUT_KEY: &str = "SocketConnectionIdleTimeout";
pub(crate) const SOCKET_CONNECTION_IDLE_TIMEOUT_DEFAULT_SECS: u64 = 18_000;

/// These are the required configuration fields.
///
/// A trait that defines the configuration setup for the application.
/// Implementors of this trait are expected to provide various configuration
/// parameters required for the application to function correctly.
pub trait SetupConfiguration: DynClone + Send + Sync + Debug {
    /// Returns the file path to the dynamic configuration file.
    fn dynamic_configuration_file(&self) -> String;

    /// Returns the refresh interval (in seconds) for reloading the dynamic configuration.
    fn dynamic_configuration_refresh_interval_secs(&self) -> u32;

    /// Returns the polling interval (in milliseconds) for watching host config file changes.
    fn host_configuration_watch_interval_ms(&self) -> u64;

    /// Returns the name of the backend `PostgreSQL` database.
    fn postgres_database(&self) -> &str;

    /// Returns the hostname of the backend `PostgreSQL` server.
    fn postgres_host_name(&self) -> &str;

    /// Returns the port number of the backend `PostgreSQL` server.
    fn postgres_port(&self) -> u16;

    /// Returns the system user for connecting to the backend `PostgreSQL` server.
    fn postgres_system_user(&self) -> &str;

    /// Returns the data user for connecting to the backend `PostgreSQL` server.
    fn postgres_data_user(&self) -> &str;

    /// Returns the password for the data user to connect to the backend `PostgreSQL` server.
    fn postgres_data_user_password(&self) -> Option<&str>;

    /// Returns the timeout duration (in seconds) for transactions.
    fn transaction_timeout_secs(&self) -> u64;

    /// Indicates whether the application should only serve on local host or
    /// be available from all addresses.
    fn use_local_host(&self) -> bool;

    /// Returns the port number on which the gateway listens.
    fn gateway_listen_port(&self) -> u16;

    /// Returns a list of role prefixes that are blocked.
    fn blocked_role_prefixes(&self) -> &[String];

    /// Returns the timeout duration (in seconds) for `PostgreSQL` commands.
    fn postgres_command_timeout_secs(&self) -> u64;

    /// Returns the hostname of the current node for the purposes of the `IsDBGrid` command.
    fn node_host_name(&self) -> &str;

    /// Returns the certificate options for SSL/TLS connections.
    fn certificate_options(&self) -> &CertificateOptions;

    /// Returns the name of the Gateway application.
    fn application_name(&self) -> &str;

    /// Returns the time to wait for `PostgreSQL` to start up before giving up.
    fn postgres_startup_wait_time_seconds(&self) -> u64;

    /// Returns the number of worker threads for the async runtime.
    fn async_runtime_worker_threads(&self) -> usize;

    /// Returns the size of the read buffer for streams.
    fn stream_read_buffer_size(&self) -> usize;

    /// Returns the size of the write buffer for streams.
    fn stream_write_buffer_size(&self) -> usize;

    /// Returns the Unix domain socket path if Unix domain socket is enabled.
    /// Returns None if Unix socket is disabled.
    fn unix_socket_path(&self) -> Option<&str>;

    /// Returns the timeout duration (in minutes) for `PostgreSQL` connections
    fn postgres_idle_connection_timeout_minutes(&self) -> u64;

    /// Returns whether TLS should be enforced for all connections.
    fn enforce_tls(&self) -> bool;

    /// Returns the file permissions for Unix socket files (octal format).
    /// Defaults to 0o660 (owner+group read/write) if not specified.
    fn unix_socket_file_permissions(&self) -> u32;

    /// Returns the kind identifier for this gateway instance.
    /// Included in the hello command's `internal` response document.
    fn instance_kind(&self) -> &str;

    /// Returns telemetry options from static setup configuration, if present.
    fn telemetry_options(&self) -> Option<&TelemetryOptions>;

    /// Provides a way to downcast the trait object to a concrete type.
    fn as_any(&self) -> &dyn std::any::Any;

    /// Returns whether refreshing settings from `pg_file_settings` is enabled.
    fn enable_pg_file_settings_refresh(&self) -> Option<bool>;
}

clone_trait_object!(SetupConfiguration);
