// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};

use crate::project::manifest;
use crate::util::StringSub;
use crate::{download, platform, Error, Result};

/// A source of targets.
#[derive(Debug)]
pub struct Provider {
    /// The globally-unique name of the provider.
    pub name: String,

    /// Manifest file in which the provider is defined.
    pub file: PathBuf,

    /// If true, targets provided by the provider appear in the global namespace
    /// instead of nested under the provider's name.
    pub global: bool,
}

impl Provider {
    #[must_use]
    pub(crate) fn new(name: &str, file: &Path, global: bool) -> Self {
        Self {
            name: name.into(),
            file: file.into(),
            global,
        }
    }
}

/// A buildable `qg` target.
#[derive(Debug)]
pub struct Target {
    /// The target's name, without a provider namespace.
    name: String,

    /// The name of the target's provider.
    provider: String,

    /// Whether the target lives in the global namespace.
    global: bool,

    /// List of targets on which this one depends, storing their full namespaced
    /// paths.
    dependencies: Vec<String>,

    /// Information about how to build the target, specific to a type of
    /// provider.
    metadata: Metadata,
}

/// Additional information about how to build a target specific to a type
/// of provider.
#[derive(Debug)]
pub enum Metadata {
    DepOnly,
    Cipd(Cipd),
    Download(Download),
}

#[derive(Debug)]
pub struct Cipd {
    pub path: String,
    pub platforms: Vec<String>,
    pub tags: Vec<String>,
    pub subdir: Option<PathBuf>,
}

impl From<manifest::CipdPackage> for Cipd {
    fn from(value: manifest::CipdPackage) -> Self {
        // TODO(frolv): This should do some verification.
        Self {
            path: value.path,
            platforms: value.platforms,
            tags: value.tags,
            subdir: value.subdir,
        }
    }
}

#[derive(Debug)]
pub struct Download {
    pub format: download::Format,
    pub url: StringSub,
    pub url_parameters: HashMap<String, String>,
    pub variants: Vec<DownloadVariant>,
}

#[derive(Debug)]
pub struct DownloadVariant {
    pub matches: VariantMatch,
    url_parameters: HashMap<String, String>,
}

#[derive(Debug)]
pub struct VariantMatch {
    system: Option<platform::System>,
    arch: Option<platform::Architecture>,
}

impl TryFrom<manifest::DownloadablePackage> for Download {
    type Error = Error;

    fn try_from(value: manifest::DownloadablePackage) -> std::result::Result<Self, Self::Error> {
        let url_parameters = value.url_parameters;
        let mut all_params: HashSet<&str> = url_parameters.keys().map(String::as_str).collect();

        let variants: Vec<DownloadVariant> = value
            .variants
            .into_iter()
            .map(|variant| {
                let mut variant_match = VariantMatch {
                    system: None,
                    arch: None,
                };

                for (var, val) in &variant.match_vars {
                    match var.as_str() {
                        "os" => variant_match.system = Some(val.parse::<platform::System>()?),
                        "arch" => variant_match.arch = Some(val.parse::<platform::Architecture>()?),
                        _ => {
                            // TODO(frolv): Return an error with the invalid variable.
                            return Err(Error::GenericErrorPlaceholder);
                        }
                    }
                }

                Ok(DownloadVariant {
                    matches: variant_match,
                    url_parameters: variant.url_parameters,
                })
            })
            .collect::<Result<Vec<_>>>()?;

        for variant in &variants {
            all_params.extend(variant.url_parameters.keys().map(String::as_str));
        }

        // Check if any of the parameters specified in the `url_parameters`
        // mapping have invalid names.
        let invalid_vars: Vec<_> = all_params
            .iter()
            .filter(|&&param| !StringSub::valid_variable_name(param))
            .collect();
        if !invalid_vars.is_empty() {
            // TODO(frolv): Return an error containing the invalid variables.
            println!("invalid URL variable names {invalid_vars:?}");
            return Err(Error::GenericErrorPlaceholder);
        }

        // Next, check the URL string itself. Each parameter substitution
        // defined within braces should exist within a provided `url_parameters`
        // mapping.
        let url: StringSub = value.url.parse()?;

        let missing_vars: Vec<_> = url.vars().filter(|&v| !all_params.contains(v)).collect();
        if !missing_vars.is_empty() {
            // TODO(frolv): Return an error containing the missing variables.
            println!("missing URL parameters {missing_vars:?}");
            return Err(Error::GenericErrorPlaceholder);
        }

        let format = match value.format.ok_or(Error::GenericErrorPlaceholder)?.as_str() {
            "bin" => {
                download::Format::Binary(value.bin_name.ok_or(Error::GenericErrorPlaceholder)?)
            }
            _ => return Err(Error::GenericErrorPlaceholder),
        };

        Ok(Self {
            format,
            url,
            url_parameters,
            variants,
        })
    }
}

impl TryFrom<manifest::TargetType> for Metadata {
    type Error = Error;

    fn try_from(value: manifest::TargetType) -> std::result::Result<Self, Self::Error> {
        match value {
            manifest::TargetType::Cipd(data) => Ok(Self::Cipd(data.into())),
            manifest::TargetType::Download(data) => data.try_into().map(Self::Download),
        }
    }
}

impl Target {
    pub(crate) fn from_manifest(
        name: &str,
        provider: &str,
        global: bool,
        target: manifest::Target,
    ) -> Result<Self> {
        let target = Self {
            name: name.to_owned(),
            provider: provider.to_owned(),
            global,
            dependencies: target.deps,
            metadata: target
                .desc
                .map_or(Ok(Metadata::DepOnly), Metadata::try_from)?,
        };

        Ok(target)
    }

    /// Returns the name of the package.
    #[must_use]
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Returns the name of the package's provider.
    #[must_use]
    pub fn provider(&self) -> &str {
        &self.provider
    }

    /// Returns true if the target is defined in the global namespace.
    #[must_use]
    pub fn is_global(&self) -> bool {
        self.global
    }

    /// Returns the package's dependencies.
    pub fn dependencies(&self) -> impl Iterator<Item = &str> {
        self.dependencies.iter().map(String::as_str)
    }

    /// Returns the fully-qualified name of the target.
    #[must_use]
    pub fn full_name(&self) -> String {
        if self.global {
            self.name.clone()
        } else {
            format!("{}:{}", self.provider, self.name)
        }
    }

    /// Returns the type of the package as a string.
    #[must_use]
    pub fn type_string(&self) -> &str {
        match self.metadata {
            Metadata::DepOnly => "dep_only",
            Metadata::Cipd(_) => "cipd",
            Metadata::Download(_) => "download",
        }
    }
}

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

    #[test]
    fn target_from_deponly() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec!["libqg".into(), "cargo".into()],
            desc: None,
        };
        let target = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap();
        assert_eq!(target.name(), "qg");
        assert_eq!(target.provider(), "qg-provider");
        assert_eq!(target.full_name(), "qg");
        assert!(target.is_global());
        assert_eq!(target.dependencies().count(), 2);
        assert_eq!(target.type_string(), "dep_only");
    }

    #[test]
    fn target_from_deponly_local() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec!["cargo".into()],
            desc: None,
        };
        let target = Target::from_manifest("qg", "qg-provider", false, manifest_target).unwrap();
        assert_eq!(target.name(), "qg");
        assert_eq!(target.provider(), "qg-provider");
        assert_eq!(target.full_name(), "qg-provider:qg");
        assert!(!target.is_global());
        assert_eq!(target.dependencies().count(), 1);
        assert_eq!(target.type_string(), "dep_only");
    }

    #[test]
    fn target_from_download_basic_valid() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec![],
            desc: Some(manifest::TargetType::Download(
                manifest::DownloadablePackage {
                    url: "https://qg.io/client".into(),
                    url_parameters: HashMap::new(),
                    variants: vec![],
                    format: Some("bin".into()),
                    bin_name: Some("qg".into()),
                },
            )),
        };
        let target = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap();
        assert_eq!(target.name(), "qg");
        assert_eq!(target.provider(), "qg-provider");
        assert_eq!(target.full_name(), "qg");
        assert!(target.is_global());
        assert_eq!(target.dependencies().count(), 0);
        assert_eq!(target.type_string(), "download");
    }

    #[test]
    fn target_from_download_params_valid() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec![],
            desc: Some(manifest::TargetType::Download(
                manifest::DownloadablePackage {
                    url: "https://qg.io/client?version={ver}".into(),
                    url_parameters: HashMap::from([("ver".into(), "1.2.4".into())]),
                    variants: vec![],
                    format: Some("bin".into()),
                    bin_name: Some("qg".into()),
                },
            )),
        };
        let target = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap();
        assert_eq!(target.name(), "qg");
        assert_eq!(target.provider(), "qg-provider");
        assert_eq!(target.full_name(), "qg");
        assert!(target.is_global());
        assert_eq!(target.dependencies().count(), 0);
        assert_eq!(target.type_string(), "download");
    }

    #[test]
    fn target_from_download_params_missing() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec![],
            desc: Some(manifest::TargetType::Download(
                manifest::DownloadablePackage {
                    url: "https://qg.io/client?version={ver}".into(),
                    url_parameters: HashMap::new(), // no `ver` defined
                    variants: vec![],
                    format: Some("bin".into()),
                    bin_name: Some("qg".into()),
                },
            )),
        };
        let err = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap_err();
        assert!(matches!(err, Error::GenericErrorPlaceholder));
    }

    #[test]
    fn target_from_download_params_invalid_name() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec![],
            desc: Some(manifest::TargetType::Download(
                manifest::DownloadablePackage {
                    url: "https://qg.io/client?version={0ver}".into(),
                    url_parameters: HashMap::from([("0ver".into(), "01.2.4".into())]),
                    variants: vec![],
                    format: Some("bin".into()),
                    bin_name: Some("qg".into()),
                },
            )),
        };
        let err = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap_err();
        assert!(matches!(err, Error::GenericErrorPlaceholder));
    }

    #[test]
    fn target_from_download_params_empty_name() {
        let manifest_target = manifest::Target {
            namespace: manifest::ProviderNamespace::Local,
            deps: vec![],
            desc: Some(manifest::TargetType::Download(
                manifest::DownloadablePackage {
                    url: "https://qg.io/client?version={}".into(),
                    url_parameters: HashMap::new(),
                    variants: vec![],
                    format: Some("bin".into()),
                    bin_name: Some("qg".into()),
                },
            )),
        };
        let err = Target::from_manifest("qg", "qg-provider", true, manifest_target).unwrap_err();
        assert!(matches!(err, Error::GenericErrorPlaceholder));
    }
}
