// 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.

#![warn(missing_docs)]

mod asset;
mod builder;
pub(crate) mod config;
mod debug;
mod family;
mod inspect;
mod typeface;

use self::asset::AssetCollection;
use self::debug::{TypefaceRequestFormatter, TypefaceResponseFormatter};
use self::family::{FamilyOrAlias, FontFamily, TypefaceQueryOverrides};
use self::typeface::{Collection as TypefaceCollection, Typeface, TypefaceInfoAndCharSet};
use anyhow::{format_err, Context as _, Error};
use fidl::endpoints::ServerEnd;
use fidl_fuchsia_fonts::{self as fonts, CacheMissPolicy};
use fidl_fuchsia_fonts_ext::{
    FontFamilyInfoExt, RequestExt, TypefaceRequestExt, TypefaceResponseExt,
};
use fidl_fuchsia_intl::LocaleId;
use fuchsia_component::server::{ServiceFs, ServiceObj};
use futures::prelude::*;
use itertools::Itertools;
use std::collections::BTreeMap;
use std::iter;
use std::sync::Arc;
use tracing::{debug, error, warn};
use unicase::UniCase;
use {
    fidl_fuchsia_fonts_experimental as fonts_exp, fuchsia_async as fasync, fuchsia_trace as trace,
};

pub use asset::{AssetId, AssetLoader};
pub use builder::FontServiceBuilder;

/// Get a field out of a `TypefaceRequest`'s `query` field as a reference, or returns early with a
/// `anyhow::Error` if the query is missing.
macro_rules! query_field {
    ($request:ident, $field:ident) => {
        $request.query.as_ref().ok_or(format_err!("Missing query"))?.$field.as_ref()
    };
}

pub enum ProviderRequestStream {
    Stable(fonts::ProviderRequestStream),
    Experimental(fonts_exp::ProviderRequestStream),
}

/// The result of a successful lookup of a font family by name. Combines a `FontFamily` and,
/// if the `FontFamilyAlias` that the client requested turned out to include
/// `TypefaceQueryOverrides` then also contains those overrides.
struct FontFamilyMatch<'a> {
    family: &'a FontFamily,
    overrides: Option<Arc<TypefaceQueryOverrides>>,
}

/// Maintains state and handles request streams for the font server.
#[derive(Debug)]
pub struct FontService<L>
where
    L: AssetLoader,
{
    assets: AssetCollection<L>,
    /// Maps the font family name from the manifest (`families[x].name`) to a FamilyOrAlias.
    families: BTreeMap<UniCase<String>, FamilyOrAlias>,
    fallback_collection: TypefaceCollection,
    /// Maps from a unique "Postscript name" to a typeface
    postscript_name_lookup: BTreeMap<String, Arc<Typeface>>,
    /// Maps from a unique "full name" to a typeface
    full_name_lookup: BTreeMap<String, Arc<Typeface>>,
    /// Holds Inspect data about manifests, families, and the fallback collection.
    // TODO(https://fxbug.dev/42165549)
    #[allow(unused)]
    inspect_data: inspect::ServiceInspectData,

    /// Indicates whether the service is running on an internal (non-production) Fuchsia build.
    is_internal_build: bool,
}

impl<L> FontService<L>
where
    L: AssetLoader,
{
    /// Resolves a font family or alias either to itself (if it's a family), or to the canonical
    /// family. If it's an alias and contains `TypefaceQueryOverrides`, then the resulting
    /// `FontFamilyMatch` will contain those overrides.
    fn resolve_alias<'a>(
        &'a self,
        family_or_alias: &'a FamilyOrAlias,
    ) -> Option<FontFamilyMatch<'a>> {
        match family_or_alias {
            FamilyOrAlias::Family(family) => Some(FontFamilyMatch { family, overrides: None }),
            FamilyOrAlias::Alias(name, overrides) => match self.families.get(name) {
                Some(FamilyOrAlias::Family(family)) => {
                    Some(FontFamilyMatch { family, overrides: overrides.clone() })
                }
                _ => None,
            },
        }
    }

    /// Get font family by name.
    fn match_family(&self, family_name: &UniCase<String>) -> Option<FontFamilyMatch<'_>> {
        self.resolve_alias(self.families.get(family_name)?)
    }

    /// Get all font families whose name contains the requested string
    fn match_families_substr(&self, family_name: String) -> impl Iterator<Item = &FontFamily> {
        self.families
            .iter()
            .filter_map(move |(key, value)| {
                // Note: This might not work for some non-Latin strings
                if key.as_ref().to_lowercase().contains(&family_name.to_lowercase()) {
                    return self.resolve_alias(value).map(|matched| matched.family);
                }
                None
            })
            .unique_by(|family| family.name.to_owned())
    }

    fn apply_query_overrides(
        mut request: fonts::TypefaceRequest,
        overrides: Arc<TypefaceQueryOverrides>,
    ) -> fonts::TypefaceRequest {
        match &mut request.query {
            Some(query) => {
                if overrides.has_style_overrides() {
                    // If query has no style at all, use the values from TypefaceQueryOverrides
                    match &mut query.style {
                        None => query.style = Some(overrides.style.clone().into()),
                        Some(style) => {
                            style.slant = style.slant.or(overrides.style.slant);
                            style.width = style.width.or(overrides.style.width);
                            style.weight = style.weight.or(overrides.style.weight);
                        }
                    }
                }

                if overrides.has_language_overrides() {
                    match &mut query.languages {
                        None => {
                            query.languages = Some(
                                overrides
                                    .languages
                                    .iter()
                                    .map(|lang| LocaleId { id: lang.to_owned() })
                                    .collect_vec(),
                            )
                        }
                        Some(_) => (),
                    }
                }
            }
            None => (),
        }
        request
    }

    async fn match_request(
        &self,
        request: fonts::TypefaceRequest,
    ) -> Result<fonts::TypefaceResponse, Error> {
        debug!("match_request: {:?}", &TypefaceRequestFormatter(&request));

        let (typeface, request) =
            if let Some(postscript_name) = query_field!(request, postscript_name) {
                (self.postscript_name_lookup.get(postscript_name).map(Arc::as_ref), request)
            } else if let Some(full_name) = query_field!(request, full_name) {
                (self.full_name_lookup.get(full_name).map(Arc::as_ref), request)
            } else {
                self.match_non_unique_typeface_request(request)?
            };

        let typeface_response = match typeface {
            Some(typeface) => self
                .assets
                .get_asset(typeface.asset_id, request.cache_miss_policy())
                .await
                .and_then(|buffer| {
                    Ok(fonts::TypefaceResponse {
                        buffer: Some(buffer),
                        buffer_id: Some(typeface.asset_id.into()),
                        font_index: Some(typeface.font_index),
                        ..Default::default()
                    })
                })
                .ok(),
            None => None,
        };

        if typeface_response.is_none() && self.is_internal_build {
            warn!("Unfulfilled request {:?}", &TypefaceRequestFormatter(&request));
        }

        let typeface_response = typeface_response.unwrap_or(fonts::TypefaceResponse::default());

        debug!("Response: {:?}", &TypefaceResponseFormatter(&typeface_response));

        // Note that not finding a typeface is not an error, as long as the query was legal.
        Ok(typeface_response)
    }

    /// This is the general case for typeface requests: lookups that are not by unique name.
    ///
    /// `request` is taken as an argument and returned because it may be modified in the process.
    fn match_non_unique_typeface_request(
        &self,
        request: fonts::TypefaceRequest,
    ) -> Result<(Option<&Typeface>, fonts::TypefaceRequest), Error> {
        let query_family = query_field!(request, family);
        let query_family_string =
            (&query_family).map(|family| family.name.clone()).unwrap_or_default();
        trace::duration!(
            c"fonts",
            c"service:match_non_unique_typeface_request",
            "family" => &query_family_string[..]
        );
        // TODO(https://fxbug.dev/42120730): If support for lazy trace args is added, include more query params, e.g.
        // code points.

        let matched_family: Option<FontFamilyMatch<'_>> =
            query_family.and_then(|family| self.match_family(&UniCase::new(family.name.clone())));

        let mut request = match &matched_family {
            Some(FontFamilyMatch { family: _, overrides: Some(overrides) }) => {
                Self::apply_query_overrides(request, overrides.clone())
            }
            _ => request,
        };

        let mut typeface = match &matched_family {
            Some(FontFamilyMatch { family, overrides: _ }) => {
                family.faces.match_request(&request)?
            }
            None => None,
        };

        // If an exact match wasn't found, but fallback families are allowed...
        if typeface.is_none() && !request.exact_family() {
            // If fallback_family is not specified by the client explicitly then copy it from
            // the matched font family.
            if query_field!(request, fallback_family).is_none() {
                if let Some(FontFamilyMatch { family, overrides: _ }) = matched_family {
                    request
                        .query
                        .as_mut()
                        .ok_or_else(|| format_err!("This should never happen"))?
                        .fallback_family = family.generic_family;
                }
            }
            typeface = self.fallback_collection.match_request(&request)?;
        }
        Ok((typeface, request))
    }

    fn get_family_info(&self, family_name: fonts::FamilyName) -> fonts::FontFamilyInfo {
        let family_name = UniCase::new(family_name.name);
        let family = self.match_family(&family_name);
        family.map_or(
            fonts::FontFamilyInfo::default(),
            |FontFamilyMatch { family, overrides: _ }| fonts::FontFamilyInfo {
                name: Some(fonts::FamilyName { name: family.name.clone() }),
                styles: Some(family.faces.get_styles().collect()),
                ..Default::default()
            },
        )
    }

    async fn get_typeface_by_id(
        &self,
        id: AssetId,
        policy: CacheMissPolicy,
    ) -> Result<fonts::TypefaceResponse, fonts_exp::Error> {
        match self.assets.get_asset(id, policy).await {
            Ok(buffer) => {
                let response = fonts::TypefaceResponse {
                    buffer: Some(buffer),
                    buffer_id: Some(id.into()),
                    font_index: None,
                    ..Default::default()
                };
                Ok(response)
            }
            Err(e) => {
                let msg = e.to_string();
                if msg.starts_with("No asset found") {
                    return Err(fonts_exp::Error::NotFound);
                }
                Err(fonts_exp::Error::Internal)
            }
        }
    }

    fn get_typefaces_by_family(
        &self,
        family_name: fonts::FamilyName,
    ) -> Result<fonts_exp::TypefaceInfoResponse, fonts_exp::Error> {
        let family = self
            .match_family(&UniCase::new(family_name.name.clone()))
            .map(|matched| matched.family)
            .ok_or(fonts_exp::Error::NotFound)?;
        let faces = family.extract_faces().map_into().collect();
        let response =
            fonts_exp::TypefaceInfoResponse { results: Some(faces), ..Default::default() };
        Ok(response)
    }

    /// Helper that runs the "match by family name" step of [`list_typefaces`].
    /// Returns a vector of all available font families whose name or alias equals (or contains, if
    /// the `MatchFamilyNameSubstring` flag is set) the name requested in `query`.
    /// If `query` or `query.family` is `None`, all families are matched.
    fn list_typefaces_match_families<'a>(
        &'a self,
        flags: fonts_exp::ListTypefacesFlags,
        request: &fonts_exp::ListTypefacesRequest,
    ) -> Box<dyn Iterator<Item = &FontFamily> + 'a> {
        match request.family.as_ref() {
            Some(fonts::FamilyName { name }) => {
                if flags.contains(fonts_exp::ListTypefacesFlags::MATCH_FAMILY_NAME_SUBSTRING) {
                    Box::new(self.match_families_substr(name.clone()))
                } else {
                    match self.match_family(&UniCase::new(name.clone())) {
                        Some(matched) => Box::new(iter::once(matched.family)),
                        None => Box::new(iter::empty()),
                    }
                }
            }
            None => Box::new(self.families.iter().filter_map(move |(_, value)| match value {
                FamilyOrAlias::Family(family) => Some(family),
                FamilyOrAlias::Alias(_, _) => None,
            })),
        }
    }

    fn list_typefaces_inner(
        &self,
        request: fonts_exp::ListTypefacesRequest,
    ) -> Result<Vec<fonts_exp::TypefaceInfo>, fonts_exp::Error> {
        let flags = request.flags.unwrap_or(fonts_exp::ListTypefacesFlags::empty());

        let matched_families = self.list_typefaces_match_families(flags, &request);

        // Flatten matches into Iter<TypefaceInfoAndCharSet>
        let matched_faces = matched_families.flat_map(|family| family.extract_faces());

        let slant_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.slant {
                Some(fonts_exp::SlantRange { lower, upper }) => {
                    // Unwrap is safe because manifest loading assigns default values if needed
                    (lower..=upper).contains(&face.style.slant.unwrap())
                }
                None => true,
            }
        };

        let weight_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.weight {
                Some(fonts_exp::WeightRange { lower, upper }) => {
                    // Unwrap is safe because manifest loading assigns default values if needed
                    (lower..=upper).contains(&face.style.weight.unwrap())
                }
                None => true,
            }
        };

        let width_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.width {
                Some(fonts_exp::WidthRange { lower, upper }) => {
                    // Unwrap is safe because manifest loading assigns default values if needed
                    (lower..=upper).contains(&face.style.width.unwrap())
                }
                None => true,
            }
        };

        let lang_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.languages.as_ref() {
                // This is O(face_langs.len() * fonts.MAX_FACE_QUERY_LANGUAGES). As of 06/2019,
                // MAX_FACE_QUERY_LANGAUGES == 8. face_langs.len() *should* be small as well.
                Some(langs) => langs.iter().all(|lang| face.languages.contains(&lang)),
                None => true,
            }
        };

        let code_point_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.code_points.as_ref() {
                Some(points) => points.iter().all(|point| face.char_set.contains(*point)),
                None => true,
            }
        };

        let generic_family_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            match request.generic_family.as_ref() {
                Some(generic_family) => {
                    face.generic_family.map_or(false, |gf| generic_family == &gf)
                }
                None => true,
            }
        };

        let total_predicate = |face: &TypefaceInfoAndCharSet| -> bool {
            slant_predicate(face)
                && weight_predicate(face)
                && width_predicate(face)
                && lang_predicate(face)
                && code_point_predicate(face)
                && generic_family_predicate(face)
        };

        // Filter
        let matched_faces = matched_faces.filter(total_predicate).map_into().collect();

        Ok(matched_faces)
    }

    fn list_typefaces(
        &self,
        request: fonts_exp::ListTypefacesRequest,
        iterator: ServerEnd<fonts_exp::ListTypefacesIteratorMarker>,
    ) -> Result<(), fonts_exp::Error> {
        let mut results = self.list_typefaces_inner(request)?;

        fasync::Task::spawn(
            async move {
                let mut stream = iterator.into_stream()?;
                while let Some(request) = stream.try_next().await? {
                    match request {
                        fonts_exp::ListTypefacesIteratorRequest::GetNext { responder } => {
                            let split_at =
                                (fonts_exp::MAX_TYPEFACE_RESULTS as usize).min(results.len());
                            // Return results in order
                            let chunk = results.drain(..split_at).collect_vec();
                            let response = fonts_exp::TypefaceInfoResponse {
                                results: Some(chunk),
                                ..Default::default()
                            };
                            responder.send(&response)?;
                        }
                    }
                }
                Ok(())
            }
            .unwrap_or_else(|e: Error| {
                error!("Error while running ListTypefacesIterator: {:?}", e)
            }),
        )
        .detach();

        Ok(())
    }

    async fn handle_font_provider_request(
        &self,
        request: fonts::ProviderRequest,
    ) -> Result<(), Error> {
        use fonts::ProviderRequest::*;

        match request {
            // TODO(https://fxbug.dev/42170326): Remove when all clients have migrated to GetTypeface
            GetFont { request, responder } => {
                let request = request.into_typeface_request();
                let response = self.match_request(request).await?.into_font_response();
                Ok(responder.send(response)?)
            }
            // TODO(https://fxbug.dev/42170326): Remove when all clients have migrated to GetFontFamilyInfo
            GetFamilyInfo { family, responder } => {
                let font_info =
                    self.get_family_info(fonts::FamilyName { name: family }).into_family_info();
                Ok(responder.send(font_info.as_ref())?)
            }
            GetTypeface { request, responder } => {
                let response = self.match_request(request).await?;
                Ok(responder.send(response)?)
            }
            GetFontFamilyInfo { family, responder } => {
                let family_info = self.get_family_info(family);
                Ok(responder.send(&family_info)?)
            }
            // TODO(https://fxbug.dev/42110254): Implement font event dispatch
            RegisterFontSetEventListener { listener: _, responder: _ } => unimplemented!(),
        }
    }

    async fn handle_experimental_request(
        &self,
        request: fonts_exp::ProviderRequest,
    ) -> Result<(), Error> {
        use fonts_exp::ProviderRequest::*;

        match request {
            GetTypefaceById { id, responder } => {
                let response = self
                    .get_typeface_by_id(AssetId(id), CacheMissPolicy::BlockUntilDownloaded)
                    .await;
                Ok(responder.send(response)?)
            }
            GetTypefacesByFamily { family, responder } => {
                let response = self.get_typefaces_by_family(family);
                Ok(responder.send(response.as_ref().map_err(|e| *e))?)
            }
            ListTypefaces { request, iterator, responder } => {
                let response = self.list_typefaces(request, iterator);
                Ok(responder.send(response)?)
            }
        }
    }

    pub async fn run(self, fs: ServiceFs<ServiceObj<'static, ProviderRequestStream>>) {
        let self_ = Arc::new(self);
        fs.for_each_concurrent(None, move |stream| self_.clone().handle_stream(stream)).await;
    }

    async fn handle_stream(self: Arc<Self>, stream: ProviderRequestStream) {
        let self_ = self.clone();
        match stream {
            ProviderRequestStream::Stable(stream) => {
                self_.as_ref().handle_stream_stable(stream).await.unwrap_or_default()
            }
            ProviderRequestStream::Experimental(stream) => {
                self_.as_ref().handle_stream_experimental(stream).await.unwrap_or_default()
            }
        }
    }

    async fn handle_stream_stable(
        &self,
        mut stream: fonts::ProviderRequestStream,
    ) -> Result<(), Error> {
        while let Some(request) = stream.try_next().await.context("Error running provider")? {
            self.handle_font_provider_request(request)
                .await
                .context("Error while handling font provider request")
                .map_err(|err| {
                    error!(?err);
                    err
                })?;
        }
        Ok(())
    }

    async fn handle_stream_experimental(
        &self,
        mut stream: fonts_exp::ProviderRequestStream,
    ) -> Result<(), Error> {
        while let Some(request) = stream.try_next().await.context("Error running provider")? {
            self.handle_experimental_request(request)
                .await
                .context("Error while handling experimental font provider request")
                .map_err(|err| {
                    error!(?err);
                    err
                })?;
        }
        Ok(())
    }
}
