// Copyright 2021 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 cml::error::Error;
use std::{fmt, str::FromStr};

/// Represents the set of features a CML file is compiled with. This struct can be
/// used to check whether a feature used in CML is enabled.
#[derive(Debug)]
pub struct FeatureSet(Vec<Feature>);

impl FeatureSet {
    /// Create an empty FeatureSet.
    pub fn empty() -> FeatureSet {
        FeatureSet(Vec::new())
    }

    /// Tests whether `feature` is enabled.
    pub fn has(&self, feature: &Feature) -> bool {
        self.0.iter().find(|f| *f == feature).is_some()
    }

    /// Returns an `Err` if `feature` is not enabled.
    pub fn check(&self, feature: Feature) -> Result<(), Error> {
        if self.has(&feature) {
            Ok(())
        } else {
            Err(Error::RestrictedFeature(feature.to_string()))
        }
    }
}

impl From<Vec<Feature>> for FeatureSet {
    fn from(features: Vec<Feature>) -> FeatureSet {
        FeatureSet(features)
    }
}

/// A feature that can be enabled/opt-into.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Feature {
    /// Enables unified services support in CML.
    Services,

    /// Allows `ComponentDecl.allowed_offers` to be specified in CML.
    DynamicOffers,

    /// Enables structured configuration support in CML.
    StructuredConfig,

    /// Allows `hub` framework capability to be used.
    Hub,

    // Allows dynamic child name lengths to exceed the default limit.
    AllowLongNames,
}

impl FromStr for Feature {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "services" => Ok(Feature::Services),
            "dynamic_offers" => Ok(Feature::DynamicOffers),
            "structured_config" => Ok(Feature::StructuredConfig),
            "hub" => Ok(Feature::Hub),
            "allow_long_names" => Ok(Feature::AllowLongNames),
            _ => Err(format!("unrecognized feature \"{}\"", s)),
        }
    }
}

impl fmt::Display for Feature {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Feature::Services => "services",
            Feature::DynamicOffers => "dynamic_offers",
            Feature::StructuredConfig => "structured_config",
            Feature::Hub => "hub",
            Feature::AllowLongNames => "allow_long_names",
        })
    }
}

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

    #[test]
    fn feature_is_parsed() {
        assert_eq!(Feature::Services, "services".parse::<Feature>().unwrap());
        assert_eq!(Feature::DynamicOffers, "dynamic_offers".parse::<Feature>().unwrap());
        assert_eq!(Feature::StructuredConfig, "structured_config".parse::<Feature>().unwrap());
        assert_eq!(Feature::Hub, "hub".parse::<Feature>().unwrap());
        assert_eq!(Feature::AllowLongNames, "allow_long_names".parse::<Feature>().unwrap());
    }

    #[test]
    fn feature_is_printed() {
        assert_eq!("services", Feature::Services.to_string());
        assert_eq!("dynamic_offers", Feature::DynamicOffers.to_string());
        assert_eq!("structured_config", Feature::StructuredConfig.to_string());
        assert_eq!("hub", Feature::Hub.to_string());
        assert_eq!("allow_long_names", Feature::AllowLongNames.to_string());
    }

    #[test]
    fn feature_set_has() {
        let set = FeatureSet::empty();
        assert!(!set.has(&Feature::Services));

        let set = FeatureSet::from(vec![Feature::Services]);
        assert!(set.has(&Feature::Services));
    }

    #[test]
    fn feature_set_check() {
        let set = FeatureSet::empty();
        assert_matches!(set.check(Feature::Services), Err(Error::RestrictedFeature(f)) if f == "services");

        let set = FeatureSet::from(vec![Feature::Services]);
        assert_matches!(set.check(Feature::Services), Ok(()));
    }
}
