#
# font_asst.py -- Font assistant routines
#
# This is open-source software licensed under a BSD license.
# Please see the file LICENSE.txt for details.
#
import os
from ginga.misc import Bunch

# lookup table of cached fonts, for backends that build them
font_cache = Bunch.Bunch(caseless=True)

# lookup table of font
font_dir = Bunch.Bunch(caseless=True)

# Set up font alias mapping
aliases = Bunch.Bunch(caseless=True)

# font scaling factors
default_scaling_factor = 1.0
scaling_factor = Bunch.Bunch(caseless=True)


def add_alias(alias_name, font_name):
    """Add an alias for a font family name.
    e.g. add_alias('fixed', 'Monotype')
    """
    global aliases
    aliases[alias_name] = font_name


def resolve_alias(alias_name, alt_font_name):
    """Resolve an alias for a font family name, providing an alternate
    name if the font alias does not exist.
    e.g. resolve_alias('fixed', 'Courier')
    """
    return aliases.get(alias_name, alt_font_name)


def get_cache(font_key):
    """Return a previously cached font object appropriate to the backend
    based on a key generated by the backend.
    Will return a KeyError in the case of a missing font.
    """
    font = font_cache[font_key]
    return font


def add_cache(font_key, font):
    """Add a `font` object to the cache, placed under key `font_key`.
    """
    global font_cache
    font_cache[font_key] = font


def add_font(font_file, font_name=None):
    """Add a font description to our directory of externally loadable fonts.
    `font_file` is the path to the font, and optional `font_name` is the
    name to register it under.
    """
    global font_dir

    if font_name is None:
        # determine family name from filename of font
        dirname, filename = os.path.split(font_file)
        font_name, ext = os.path.splitext(filename)

    font_dir[font_name] = Bunch.Bunch(name=font_name, font_path=font_file)

    return font_name


def have_font(font_name):
    """Return True if the given font name is registered as one of our
    externally loadable fonts.  If `font_name` is not found, it will try
    to look it up as an alias and report if that is found.
    """
    if font_name in font_dir:
        return True

    # try it as an alias
    font_name = resolve_alias(font_name, font_name)
    return font_name in font_dir


def get_loadable_fonts():
    """Return the sequence of externally loadable fonts.
    """
    return list(font_dir.keys())


def get_font_info(font_name, subst_ok=True):
    """Return known info on an externally loadable font (including its path).
    `font_name` is assumed to have already been resolved from an alias.
    Will return a KeyError in the case of a missing font, unless
    subst_ok is True, in which case an alternate font may be returned.
    """
    global font_dir
    if font_name in font_dir:
        font_info = font_dir[font_name]
    elif subst_ok:
        # substitute an alternate font
        font_name = resolve_alias('fixed', 'fixed')
        font_info = font_dir[font_name]
    else:
        raise KeyError(font_name)

    return font_info


def remove_font(font_name):
    """Remove `font_name` from the directory of loadable fonts.
    """
    global font_dir
    try:
        del font_dir[font_name]
    except KeyError:
        pass


def scale_fontsize(key, fontsize):
    factor = scaling_factor.get(key, default_scaling_factor)
    return int(round(fontsize * factor))


def set_scale_factor(key, factor):
    """Set the scale factor for a renderer `key` to `factor`.
    """
    global scaling_factor
    scaling_factor[key] = factor


# --- Set up bundled fonts ---

fontdir, xx = os.path.split(__file__)

known_font = os.path.join(fontdir, 'Roboto', 'Roboto-Regular.ttf')
add_font(known_font, font_name='roboto')
add_alias('fixed', 'roboto')
