// 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},
    fuchsia_url::pkg_url::PkgUrl,
    fuchsia_zircon::Duration,
    serde::Deserialize,
    std::{cmp, fs::File, io::Read, num::NonZeroU64},
    thiserror::Error,
};

/// Static service configuration options.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct Config {
    poll_frequency: Option<Duration>,
    update_package_url: Option<PkgUrl>,
}

impl Config {
    pub fn poll_frequency(&self) -> Option<Duration> {
        self.poll_frequency
    }

    pub fn update_package_url(&self) -> Option<&PkgUrl> {
        self.update_package_url.as_ref()
    }

    pub fn load_from_config_data_or_default() -> Config {
        let f = match File::open("/config/data/ota_config.json") {
            Ok(f) => f,
            Err(e) => {
                fx_log_info!("no config found, using defaults: {:#}", anyhow!(e));
                return Config::default();
            }
        };

        Self::load(f).unwrap_or_else(|e| {
            fx_log_err!("unable to load config, using defaults: {:#}", anyhow!(e));
            Config::default()
        })
    }

    fn load(r: impl Read) -> Result<Config, ConfigLoadError> {
        #[derive(Debug, Deserialize)]
        #[serde(deny_unknown_fields)]
        struct ParseConfig {
            poll_frequency_minutes: Option<NonZeroU64>,
            update_package_url: Option<PkgUrl>,
        }

        let config = serde_json::from_reader::<_, ParseConfig>(r)?;
        if config.update_package_url.as_ref().map(|url| url.resource().is_some()).unwrap_or(false) {
            return Err(ConfigLoadError::UpdatePackageUrlContainsResource);
        }

        Ok(Config {
            poll_frequency: config.poll_frequency_minutes.map(|freq| {
                // zx::Duration will wrap on overflow when converting to nanoseconds. Ensure a
                // config file cannot specify a negative duration by clamping to the maximum number
                // of minutes that can be represented as nanoseconds in an i64.
                let max_minutes_duration =
                    Duration::from_nanos(std::i64::MAX).into_minutes() as u64;
                Duration::from_minutes(cmp::min(freq.get(), max_minutes_duration) as i64)
            }),
            update_package_url: config.update_package_url,
        })
    }
}

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

    #[error("update_package_url must not contain a resource path")]
    UpdatePackageUrlContainsResource,
}

#[cfg(test)]
#[derive(Debug)]
pub struct ConfigBuilder(Config);

#[cfg(test)]
impl ConfigBuilder {
    pub fn new() -> Self {
        Self(Config::default())
    }

    pub fn poll_frequency(mut self, duration: impl Into<Duration>) -> Self {
        self.0.poll_frequency = Some(duration.into());
        self
    }

    pub fn build(self) -> Config {
        self.0
    }
}

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

    fn verify_load(input: serde_json::Value, expected: Config) {
        let input = input.to_string();

        assert_eq!(Config::load(input.as_bytes()).unwrap(), expected);
    }

    #[test]
    fn test_load() {
        verify_load(
            json!({
                "update_package_url": "fuchsia-pkg://fuchsia.com/abc",
                "poll_frequency_minutes": 123,
            }),
            Config {
                poll_frequency: Some(Duration::from_minutes(123)),
                update_package_url: Some(PkgUrl::parse("fuchsia-pkg://fuchsia.com/abc").unwrap()),
            },
        );
    }

    #[test]
    fn test_missing_fields_are_defaults() {
        verify_load(
            json!({
                "update_package_url": "fuchsia-pkg://fuchsia.com/the-update",
            }),
            Config {
                poll_frequency: None,
                update_package_url: Some(
                    PkgUrl::parse("fuchsia-pkg://fuchsia.com/the-update").unwrap(),
                ),
            },
        );
        verify_load(
            json!({
                "poll_frequency_minutes": 1,
            }),
            Config { poll_frequency: Some(Duration::from_minutes(1)), update_package_url: None },
        );
    }

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

    #[test]
    fn test_load_empty_is_default() {
        assert_matches!(
            Config::load("{}".as_bytes()),
            Ok(ref config) if config == &Config::default());
    }

    #[test]
    fn test_load_rejects_invalid() {
        assert_matches!(
            Config::load("not json".as_bytes()),
            Err(ConfigLoadError::Parse(ref err)) if err.is_syntax());
    }

    #[test]
    fn test_load_rejects_resource_path() {
        let input = json!({
            "update_package_url": "fuchsia-pkg://fuchsia.com/update/0#unexpected/resource.path",
        })
        .to_string();

        assert_matches!(
            Config::load(input.as_bytes()),
            Err(ConfigLoadError::UpdatePackageUrlContainsResource)
        );
    }

    #[test]
    fn test_load_rejects_zero_poll_frequency() {
        let input = json!({
            "poll_frequency_minutes": 0,
        })
        .to_string();

        assert_matches!(
            Config::load(input.as_bytes()),
            Err(ConfigLoadError::Parse(ref err)) if err.is_data());
    }

    #[test]
    fn test_load_clamps_large_poll_frequency() {
        let max_duration = Duration::from_nanos(std::i64::MAX);
        let max_duration_minutes = max_duration.into_minutes();

        let verify_clamp = |minutes| {
            verify_load(
                json!({
                    "poll_frequency_minutes": minutes,
                }),
                Config {
                    poll_frequency: Some(Duration::from_minutes(max_duration_minutes)),
                    update_package_url: None,
                },
            );
        };

        verify_clamp(max_duration_minutes as u64);
        verify_clamp(max_duration_minutes as u64 + 1);
        verify_clamp(std::i64::MAX as u64);
        verify_clamp(std::u64::MAX);
    }
}
