// Copyright 2018 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 {
    super::{
        asset::{AssetCollectionBuilder, AssetLoader, AssetLoaderImpl},
        family::{FamilyOrAliasBuilder, FontFamilyBuilder},
        inspect::ServiceInspectData,
        typeface::{Typeface, TypefaceCollectionBuilder, TypefaceId},
        FontService,
    },
    anyhow::{format_err, Error},
    font_info::FontInfoLoaderImpl,
    fuchsia_inspect as finspect,
    fuchsia_syslog::fx_vlog,
    fuchsia_trace as trace,
    manifest::{v2, FontManifestWrapper, FontsManifest},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Display},
        path::{Path, PathBuf},
        sync::Arc,
    },
    thiserror::Error,
    unicase::UniCase,
};

/// Builder for [`FontService`]. Allows populating the fields that remain immutable for the
/// lifetime of the service.
///
/// Create a new builder with [`new()`](FontServiceBuilder::new), then populate using
/// [`load_manifest()`](FontServiceBuilder::load_manifest), and finally construct a `FontService`
/// using [`build()`](FontServiceBuilder::build).
#[derive(Debug)]
pub struct FontServiceBuilder<'a, L>
where
    L: AssetLoader,
{
    manifests: Vec<ManifestOrPath>,
    assets: AssetCollectionBuilder<L>,
    /// Maps the font family name from the manifest (`families.family`) to a FamilyOrAlias.
    families: BTreeMap<UniCase<String>, FamilyOrAliasBuilder>,
    fallback_collection: TypefaceCollectionBuilder,
    inspect_root: &'a finspect::Node,
}

impl<'a> FontServiceBuilder<'a, AssetLoaderImpl> {
    /// Creates a new, empty builder with a real asset loader.
    pub fn with_default_asset_loader(
        cache_capacity_bytes: u64,
        inspect_root: &'a finspect::Node,
    ) -> FontServiceBuilder<'a, AssetLoaderImpl> {
        FontServiceBuilder::<'a, AssetLoaderImpl>::new(
            AssetLoaderImpl::new(),
            cache_capacity_bytes,
            inspect_root,
        )
    }
}

impl<'a, L> FontServiceBuilder<'a, L>
where
    L: AssetLoader,
{
    /// Creates a new, empty builder.
    pub fn new(
        asset_loader: L,
        default_cache_capacity_bytes: u64,
        inspect_root: &'a finspect::Node,
    ) -> FontServiceBuilder<'a, L> {
        FontServiceBuilder {
            manifests: vec![],
            assets: AssetCollectionBuilder::new(asset_loader, default_cache_capacity_bytes, inspect_root),
            families: BTreeMap::new(),
            fallback_collection: TypefaceCollectionBuilder::new(),
            inspect_root,
        }
    }

    /// Add a manifest path to be parsed and processed.
    pub fn add_manifest_from_file(&mut self, manifest_path: &Path) -> &mut Self {
        self.manifests.push(ManifestOrPath::Path(manifest_path.to_path_buf()));
        self
    }

    /// Adds a parsed manifest to be processed.
    #[allow(dead_code)]
    #[cfg(test)]
    pub fn add_manifest(&mut self, manifest_wrapper: FontManifestWrapper) -> &mut Self {
        self.manifests.push(ManifestOrPath::Manifest(manifest_wrapper));
        self
    }

    /// Tries to build a [`FontService`] from the provided manifests, with some additional error
    /// checking.
    pub async fn build(mut self) -> Result<FontService<L>, Error> {
        let manifest_paths = self.manifests.iter().map(ManifestOrPath::to_string).collect();
        let manifests: Result<Vec<(FontManifestWrapper, Option<PathBuf>)>, Error> = self
            .manifests
            .drain(..)
            .map(|manifest_or_path| match manifest_or_path {
                ManifestOrPath::Manifest(manifest) => Ok((manifest, None)),
                ManifestOrPath::Path(path) => {
                    fx_vlog!(1, "Loading manifest {:?}", &path);
                    Ok((FontsManifest::load_from_file(&path)?, Some(path)))
                }
            })
            .collect();

        let mut cache_size_bytes: Option<u64> = None;

        for (wrapper, path) in manifests? {
            match wrapper {
                FontManifestWrapper::Version1(v1) => {
                    self.add_fonts_from_manifest_v1(v1, path).await?
                }
                FontManifestWrapper::Version2(v2) => {
                    // Update the cache size from the first manifest that has it. (In production use
                    // cases, there will only be one manifest.)
                    if v2.settings.cache_size_bytes.is_some() && cache_size_bytes.is_none() {
                        cache_size_bytes = v2.settings.cache_size_bytes.clone();
                    }
                    self.add_fonts_from_manifest_v2(v2, path).await?
                }
            }
        }

        if let Some(cache_size_bytes) = cache_size_bytes {
            self.assets.set_cache_capacity(cache_size_bytes);
        }

        // It's fine to have no fallback collection IFF we loaded an empty manifest.
        if self.fallback_collection.is_empty() && !self.families.is_empty() {
            return Err(FontServiceBuilderError::NoFallbackCollection.into());
        }

        let assets = self.assets.build();
        let families = self.families.into_iter().map(|(key, value)| (key, value.build())).collect();
        let fallback_collection = self.fallback_collection.build();

        let inspect_data = ServiceInspectData::new(
            self.inspect_root,
            manifest_paths,
            &assets,
            &families,
            &fallback_collection,
        );

        Ok(FontService { assets, families, fallback_collection, inspect_data })
    }

    async fn add_fonts_from_manifest_v2(
        &mut self,
        manifest: v2::FontsManifest,
        manifest_path: Option<PathBuf>,
    ) -> Result<(), Error> {
        // Hold on to the typefaces defined in this manifest so that they can be referenced when
        // building the fallback chain.
        let mut manifest_typefaces: BTreeMap<TypefaceId, Arc<Typeface>> = BTreeMap::new();

        for mut manifest_family in manifest.families {
            // Register the family itself
            let family_name = UniCase::new(manifest_family.name.clone());
            let family = match self.families.entry(family_name.clone()).or_insert_with(|| {
                FamilyOrAliasBuilder::Family(FontFamilyBuilder::new(
                    family_name.to_string(),
                    manifest_family.generic_family,
                ))
            }) {
                FamilyOrAliasBuilder::Family(f) => f,
                FamilyOrAliasBuilder::Alias(_, _) => {
                    return Err(FontServiceBuilderError::AliasFamilyConflict {
                        conflicting_name: family_name.to_string(),
                        manifest_path: manifest_path.clone(),
                    }
                    .into());
                }
            };

            // Register the family's assets and their typefaces.

            // We have to use `.drain()` here (instead of moving `assets` out) in order to leave
            // `manifest_family` in a valid state to be able to keep using it further down.
            for manifest_asset in manifest_family.assets.drain(..) {
                let asset_id = self.assets.add_or_get_asset_id(&manifest_asset);
                for manifest_typeface in manifest_asset.typefaces {
                    if manifest_typeface.code_points.is_empty() {
                        return Err(FontServiceBuilderError::NoCodePoints {
                            asset_name: manifest_asset.file_name.to_string(),
                            typeface_idx: manifest_typeface.index,
                            manifest_path: manifest_path.clone(),
                        }
                        .into());
                    }
                    let generic_family = manifest_family.generic_family;
                    let typeface_id = TypefaceId { asset_id, index: manifest_typeface.index };
                    // Deduplicate typefaces across multiple manifests
                    if !family.has_typeface_id(&typeface_id) {
                        // .unwrap() because we already checked for missing code points above
                        let typeface = Arc::new(
                            Typeface::new(asset_id, manifest_typeface, generic_family).unwrap(),
                        );
                        manifest_typefaces.insert(typeface_id, typeface.clone());
                        family.add_typeface_once(typeface);
                    }
                }
            }

            // Above, we're working with `family` mutably borrowed from `self.families`. We have to
            // finish using any mutable references to `self.families` before we can create further
            // references to `self.families` below.

            // Register aliases
            let aliases = FamilyOrAliasBuilder::aliases_from_family(&manifest_family);
            for (key, value) in aliases {
                match self.families.get(&key) {
                    None => {
                        self.families.insert(key, value);
                    }
                    Some(FamilyOrAliasBuilder::Family(_)) => {
                        return Err(FontServiceBuilderError::AliasFamilyConflict {
                            conflicting_name: key.to_string(),
                            manifest_path: manifest_path.clone(),
                        }
                        .into());
                    }
                    Some(FamilyOrAliasBuilder::Alias(other_family_name, _)) => {
                        // If the alias exists then it must be for the same font family.
                        if *other_family_name != family_name {
                            return Err(FontServiceBuilderError::AmbiguousAlias {
                                alias: key.to_string(),
                                canonical_1: other_family_name.to_string(),
                                canonical_2: family_name.to_string(),
                                manifest_path: manifest_path.clone(),
                            }
                            .into());
                        }
                    }
                }
            }
        }

        // We add all the fallback typefaces, preserving their order from the product font
        // configuration file.
        //
        // Unfortunately, when there are multiple manifests with fallback chains, the best we can
        // do is concatenate the fallback chains (with de-duplication). Multiple manifests are not
        // expected in production use cases, so this isn't as awful as it sounds.
        for fallback_typeface in &manifest.fallback_chain {
            let asset_id = self
                .assets
                .get_asset_id_by_name(&fallback_typeface.file_name)
                .ok_or_else(|| FontServiceBuilderError::UnknownFallbackEntry {
                    file_name: fallback_typeface.file_name.clone(),
                    index: fallback_typeface.index,
                    manifest_path: manifest_path.clone(),
                })?;

            let typeface_id = TypefaceId { asset_id, index: fallback_typeface.index };
            if !self.fallback_collection.has_typeface_id(&typeface_id) {
                let typeface = manifest_typefaces
                    .get(&typeface_id)
                    .expect("Invalid state in FontServiceBuilder")
                    .clone();
                self.fallback_collection.add_typeface_once(typeface);
            }
        }

        Ok(())
    }

    async fn add_fonts_from_manifest_v1(
        &mut self,
        manifest_v1: FontsManifest,
        manifest_path: Option<PathBuf>,
    ) -> Result<(), Error> {
        let path_string: String = manifest_path
            .as_ref()
            .map(|path| path.to_string_lossy().to_string())
            .unwrap_or_default();
        trace::duration!(
                "fonts",
                "font_service:builder:add_fonts_from_manifest_v2",
                "path" => &path_string[..]);
        let manifest_v2 = self.convert_manifest_v1_to_v2(manifest_v1).await.map_err(|e| {
            FontServiceBuilderError::ConversionFromV1 {
                manifest_path: manifest_path.clone(),
                cause: e.into(),
            }
        })?;
        self.add_fonts_from_manifest_v2(manifest_v2, manifest_path).await
    }

    /// Converts data format from manifest v1 to v2 and loads character sets for any typefaces that
    /// lack them.
    async fn convert_manifest_v1_to_v2(
        &self,
        manifest_v1: FontsManifest,
    ) -> Result<v2::FontsManifest, Error> {
        let mut manifest_v2 = v2::FontsManifest::try_from(manifest_v1)?;
        let asset_loader = AssetLoaderImpl::new();
        let font_info_loader = FontInfoLoaderImpl::new()?;

        for manifest_family in &mut manifest_v2.families {
            for manifest_asset in &mut manifest_family.assets {
                for manifest_typeface in &mut manifest_asset.typefaces {
                    if manifest_typeface.code_points.is_empty() {
                        match &manifest_asset.location {
                            v2::AssetLocation::LocalFile(v2::LocalFileLocator { directory }) => {
                                let asset_path = directory.join(&manifest_asset.file_name);
                                let buffer = asset_loader.load_vmo_from_path(&asset_path)?;
                                let font_info = {
                                    trace::duration!("fonts", "FontInfoLoaderImpl:load_font_info");
                                    font_info_loader
                                        .load_font_info(buffer, manifest_typeface.index)?
                                };
                                manifest_typeface.code_points = font_info.char_set;
                            }
                            _ => {
                                return Err(format_err!(
                                    "Impossible asset location: {:?}",
                                    &manifest_asset
                                ));
                            }
                        }
                    }
                }
            }
        }

        Ok(manifest_v2)
    }
}

#[allow(dead_code)]
#[derive(Debug)]
enum ManifestOrPath {
    Manifest(FontManifestWrapper),
    Path(PathBuf),
}

impl Display for ManifestOrPath {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ManifestOrPath::Manifest(_manifest) => write!(f, "{}", "FontManifestWrapper {{ ... }}"),
            ManifestOrPath::Path(path) => write!(f, "{}", path.to_string_lossy().to_string()),
        }
    }
}

/// Errors arising from the use of [`FontServiceBuilder`].
#[derive(Debug, Error)]
pub enum FontServiceBuilderError {
    /// A name was used as both a canonical family name and a font family alias.
    #[error(
        "Conflict in {:?}: {} cannot be both a canonical family name and an alias",
        manifest_path,
        conflicting_name
    )]
    AliasFamilyConflict { conflicting_name: String, manifest_path: Option<PathBuf> },

    /// One string was used as an alias for two different font families.
    #[error(
        "Conflict in {:?}: {} cannot be an alias for both {} and {}",
        manifest_path,
        alias,
        canonical_1,
        canonical_2
    )]
    AmbiguousAlias {
        alias: String,
        canonical_1: String,
        canonical_2: String,
        manifest_path: Option<PathBuf>,
    },

    /// Something went wrong when converting a manifest from v1 to v2.
    #[error("Conversion from manifest v1 failed in {:?}: {:?}", manifest_path, cause)]
    ConversionFromV1 {
        manifest_path: Option<PathBuf>,
        #[source]
        cause: Error,
    },

    /// The font manifest's fallback chain referenced an undeclared typeface.
    #[error(
        "Unknown typeface in fallback chain in {:?}: file name \'{}\', index {}",
        manifest_path,
        file_name,
        index
    )]
    UnknownFallbackEntry { file_name: String, index: u32, manifest_path: Option<PathBuf> },

    /// None of the loaded manifests contained a non-empty fallback chain.
    #[error("Need at least one fallback font family")]
    NoFallbackCollection,

    /// The manifest did not have defined code points for a particular typeface.
    #[error("Missing code points for \"{}\"[{}] in {:?}", asset_name, typeface_idx, manifest_path)]
    NoCodePoints { asset_name: String, typeface_idx: u32, manifest_path: Option<PathBuf> },
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::font_service::{
            family::{FamilyOrAlias, FontFamily},
            typeface::Collection as TypefaceCollection,
            AssetId,
        },
        char_set::CharSet,
        fidl_fuchsia_fonts::{GenericFontFamily, Slant, Width, WEIGHT_BOLD, WEIGHT_NORMAL},
        manifest::{serde_ext::StyleOptions, v2},
        maplit::{btreemap, btreeset},
        pretty_assertions::assert_eq,
        std::sync::Arc,
        unicase::UniCase,
    };

    #[fuchsia_async::run_singlethreaded(test)]
    async fn test_multiple_overlapping_manifests() -> Result<(), Error> {
        let inspector = finspect::Inspector::new();
        let mut builder = FontServiceBuilder::with_default_asset_loader(5000, inspector.root());
        builder
            .add_manifest(FontManifestWrapper::Version2(v2::FontsManifest {
                families: vec![v2::Family {
                    name: "Alpha".to_string(),
                    aliases: vec![v2::FontFamilyAliasSet::without_overrides(vec![
                        "A", "Aleph", "Alif",
                    ])?],
                    generic_family: Some(GenericFontFamily::SansSerif),
                    assets: vec![
                        v2::Asset {
                            file_name: "Alpha-Regular.ttf".to_string(),
                            location: v2::AssetLocation::LocalFile(v2::LocalFileLocator {
                                directory: PathBuf::from("/pkg/config/data/assets"),
                            }),
                            typefaces: vec![v2::Typeface {
                                index: 0,
                                languages: vec!["en".to_string()],
                                style: v2::Style {
                                    slant: Slant::Upright,
                                    weight: WEIGHT_NORMAL,
                                    width: Width::Normal,
                                },
                                code_points: CharSet::new(vec![0x1, 0x2, 0x3]),
                            }],
                        },
                        v2::Asset {
                            file_name: "Alpha-Bold.ttf".to_string(),
                            location: v2::AssetLocation::LocalFile(v2::LocalFileLocator {
                                directory: PathBuf::from("/pkg/config/data/assets"),
                            }),
                            typefaces: vec![v2::Typeface {
                                index: 0,
                                languages: vec!["en".to_string()],
                                style: v2::Style {
                                    slant: Slant::Upright,
                                    weight: WEIGHT_BOLD,
                                    width: Width::Normal,
                                },
                                code_points: CharSet::new(vec![0x1, 0x2, 0x3]),
                            }],
                        },
                    ],
                }],
                fallback_chain: vec![
                    v2::TypefaceId { file_name: "Alpha-Bold.ttf".to_string(), index: 0 },
                    v2::TypefaceId { file_name: "Alpha-Regular.ttf".to_string(), index: 0 },
                ],
                settings: v2::Settings { cache_size_bytes: Some(12345) },
            }))
            .add_manifest(FontManifestWrapper::Version2(v2::FontsManifest {
                families: vec![v2::Family {
                    name: "Alpha".to_string(),
                    aliases: vec![
                        v2::FontFamilyAliasSet::without_overrides(vec![
                            "A",
                            "Aleph",
                            "Alpha Ordinary",
                        ])?,
                        // Note different languages in second manifest's "Alif" alias
                        v2::FontFamilyAliasSet::new(
                            vec!["Alif"],
                            StyleOptions::default(),
                            vec!["en", "ar"],
                        )?,
                    ],
                    generic_family: Some(GenericFontFamily::SansSerif),
                    assets: vec![v2::Asset {
                        file_name: "Alpha-Regular.ttf".to_string(),
                        location: v2::AssetLocation::LocalFile(v2::LocalFileLocator {
                            directory: PathBuf::from("/pkg/config/data/assets"),
                        }),
                        typefaces: vec![v2::Typeface {
                            index: 0,
                            languages: vec!["en".to_string()],
                            style: v2::Style {
                                slant: Slant::Upright,
                                weight: WEIGHT_NORMAL,
                                width: Width::Expanded, // Note difference
                            },
                            code_points: CharSet::new(vec![0x1, 0x2, 0x3]),
                        }],
                    }],
                }],
                fallback_chain: vec![v2::TypefaceId {
                    file_name: "Alpha-Regular.ttf".to_string(),
                    index: 0,
                }],
                settings: v2::Settings { cache_size_bytes: Some(99999) },
            }));

        let service = builder.build().await?;

        let expected_typeface_regular = Arc::new(Typeface {
            asset_id: AssetId(0),
            font_index: 0,
            slant: Slant::Upright,
            weight: WEIGHT_NORMAL,
            width: Width::Normal, // First version wins
            languages: btreeset!["en".to_string()],
            char_set: CharSet::new(vec![0x1, 0x2, 0x3]),
            generic_family: Some(GenericFontFamily::SansSerif),
        });

        let expected_typeface_bold = Arc::new(Typeface {
            asset_id: AssetId(1),
            font_index: 0,
            slant: Slant::Upright,
            weight: WEIGHT_BOLD,
            width: Width::Normal,
            languages: btreeset!["en".to_string()],
            char_set: CharSet::new(vec![0x1, 0x2, 0x3]),
            generic_family: Some(GenericFontFamily::SansSerif),
        });

        assert_eq!(
            service.families,
            btreemap!(
            UniCase::new("Alpha".to_string()) =>
                FamilyOrAlias::Family(FontFamily {
                    name: "Alpha".to_string(),
                    faces: TypefaceCollection {
                        faces: vec![
                            expected_typeface_regular.clone(),
                            expected_typeface_bold.clone()
                        ]
                    },
                    generic_family: Some(GenericFontFamily::SansSerif)
            }),
            UniCase::new("A".to_string()) =>
                FamilyOrAlias::Alias(UniCase::new("Alpha".to_string()), None),
            UniCase::new("Aleph".to_string()) =>
                FamilyOrAlias::Alias(UniCase::new("Alpha".to_string()), None),
            // First version of "Alif" wins
            UniCase::new("Alif".to_string()) =>
                FamilyOrAlias::Alias(UniCase::new("Alpha".to_string()), None),
            UniCase::new("Alpha Ordinary".to_string()) =>
                FamilyOrAlias::Alias(UniCase::new("Alpha".to_string()), None),
            UniCase::new("AlphaOrdinary".to_string()) =>
                FamilyOrAlias::Alias(UniCase::new("Alpha".to_string()), None),)
        );

        assert_eq!(service.assets.len(), 2);

        assert_eq!(
            service.fallback_collection,
            TypefaceCollection {
                faces: vec![expected_typeface_bold.clone(), expected_typeface_regular.clone()]
            }
        );

        assert_eq!(service.assets.cache_capacity_bytes().await, 12345);

        Ok(())
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn test_empty_manifest() -> Result<(), Error> {
        let inspector = finspect::Inspector::new();
        let manifest = FontManifestWrapper::Version2(v2::FontsManifest::empty());
        let mut builder = FontServiceBuilder::with_default_asset_loader(5000, inspector.root());
        builder.add_manifest(manifest);
        builder.build().await?; // Should succeed
        Ok(())
    }
}
