// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    anyhow::anyhow,
    fuchsia_syslog::{fx_log_err, fx_log_info},
    serde::Deserialize,
    std::{
        fs::File,
        io::{BufReader, Read},
    },
    thiserror::Error,
};

/// Static service configuration options.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct Config {
    enable_dynamic_configuration: bool,
    persisted_repos_dir: String,
}

impl Config {
    pub fn enable_dynamic_configuration(&self) -> bool {
        self.enable_dynamic_configuration
    }

    pub fn persisted_repos_dir(&self) -> Option<&str> {
        match self.persisted_repos_dir.as_str() {
            "" => None,
            _ => Some(&self.persisted_repos_dir),
        }
    }

    pub fn load_from_config_data_or_default() -> Config {
        let dynamic_config = match File::open("/config/data/config.json") {
            Ok(f) => Self::load_enable_dynamic_config(BufReader::new(f)).unwrap_or_else(|e| {
                fx_log_err!("unable to load config, using defaults: {:#}", anyhow!(e));
                Config::default()
            }),
            Err(e) => {
                fx_log_info!("no config found, using defaults: {:#}", anyhow!(e));
                Config::default()
            }
        };

        let repo_config = match File::open("/config/data/persisted_repos_dir.json") {
            Ok(f) => Self::load_persisted_repos_config(BufReader::new(f)).unwrap_or_else(|e| {
                fx_log_err!("unable to load config, using defaults: {:#}", anyhow!(e));
                Config::default()
            }),
            Err(e) => {
                fx_log_info!("no config found, using defaults: {:#}", anyhow!(e));
                Config::default()
            }
        };

        Config {
            enable_dynamic_configuration: dynamic_config.enable_dynamic_configuration,
            persisted_repos_dir: repo_config.persisted_repos_dir,
        }
    }

    fn load_enable_dynamic_config(r: impl Read) -> Result<Config, ConfigLoadError> {
        #[derive(Debug, Deserialize)]
        #[serde(deny_unknown_fields)]
        struct ParseConfig {
            enable_dynamic_configuration: bool,
        }

        let parse_config = serde_json::from_reader::<_, ParseConfig>(r)?;

        Ok(Config {
            enable_dynamic_configuration: parse_config.enable_dynamic_configuration,
            ..Default::default()
        })
    }

    fn load_persisted_repos_config(r: impl Read) -> Result<Config, ConfigLoadError> {
        #[derive(Debug, Deserialize)]
        #[serde(deny_unknown_fields)]
        struct ParseConfig {
            persisted_repos_dir: String,
        }

        let parse_config = serde_json::from_reader::<_, ParseConfig>(r)?;

        Ok(Config { persisted_repos_dir: parse_config.persisted_repos_dir, ..Default::default() })
    }
}

#[derive(Debug, Error)]
enum ConfigLoadError {
    #[error("parse error")]
    Parse(#[from] serde_json::Error),
}

#[cfg(test)]
mod tests {
    use {super::*, assert_matches::assert_matches, serde_json::json};

    fn verify_load_dyn(input: serde_json::Value, expected: Config) {
        assert_eq!(
            Config::load_enable_dynamic_config(input.to_string().as_bytes())
                .expect("json value to be valid"),
            expected
        );
    }

    fn verify_load_repo(input: serde_json::Value, expected: Config) {
        assert_eq!(
            Config::load_persisted_repos_config(input.to_string().as_bytes())
                .expect("json value to be valid"),
            expected
        );
    }

    #[test]
    fn test_load_valid_configs() {
        for val in [true, false].iter() {
            verify_load_dyn(
                json!({
                    "enable_dynamic_configuration": *val,
                }),
                Config { enable_dynamic_configuration: *val, ..Default::default() },
            );
        }

        verify_load_repo(
            json!({
                "persisted_repos_dir": "boo",
            }),
            Config { persisted_repos_dir: "boo".to_string(), ..Default::default() },
        )
    }

    #[test]
    fn test_load_errors_on_unknown_field() {
        assert_matches!(
            Config::load_enable_dynamic_config(
                json!({
                    "enable_dynamic_configuration": false,
                    "unknown_field": 3
                })
                .to_string()
                .as_bytes()
            ),
            Err(ConfigLoadError::Parse(_))
        );
        assert_matches!(
            Config::load_persisted_repos_config(
                json!({
                    "persisted_repos_dir": "boo".to_string(),
                    "unknown_field": 3
                })
                .to_string()
                .as_bytes()
            ),
            Err(ConfigLoadError::Parse(_))
        );
    }

    #[test]
    fn test_no_config_data_is_default() {
        assert_eq!(Config::load_from_config_data_or_default(), Config::default());
    }

    #[test]
    fn test_default_disables_dynamic_configuration() {
        assert_eq!(Config::default().enable_dynamic_configuration, false);
    }

    #[test]
    fn test_default_disables_persisted_repos() {
        assert_eq!(Config::default().persisted_repos_dir(), None);
    }
}
