# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import re
import collections
from style_variable_generator.color import Color
from style_variable_generator.opacity import Opacity
from abc import ABC, abstractmethod


class Modes:
    LIGHT = 'light'
    DARK = 'dark'
    DEBUG = 'debug'
    # The mode that colors will fallback to when not specified in a
    # non-default mode. An error will be raised if a color in any mode is
    # not specified in the default mode.
    DEFAULT = LIGHT
    ALL = [LIGHT, DARK, DEBUG]


class VariableType:
    COLOR = 'color'
    OPACITY = 'opacity'
    UNTYPED_CSS = 'untyped_css'
    TYPEFACE = 'typeface'
    FONT_FAMILY = 'font_family'


class StyleVariable(object):
    '''An intermediate representation of a single variable that the generator
       knows about.

       Some JSON entries will generate multiple StyleVariables (e.g when
       generate_per_mode is true), and different Generators may create multiple
       per-platform variables (e.g CSS generates an var and var-rgb).
    '''

    def __init__(self, variable_type, name, json_value, context):
        if not re.match(r'^[a-z0-9_\.\-]+$', name):
            raise ValueError(name + ' is not a valid variable name ' +
                             '(lower case, 0-9, _)')
        self.variable_type = variable_type
        self.name = name
        self.json_value = json_value
        self.context = context or {}


class Submodel(ABC):
    '''Abstract Base Class for all Submodels.'''

    @abstractmethod
    def Add(self, name, value_obj, context):
        '''Adds the a variable represented by |value_obj| to the submodel.
        Returns a list of |StyleVariable| objects representing the variables
        added.
        '''
        assert False

    # Submodels are expected to provide dict-like interfaces.
    @abstractmethod
    def keys(self):
        assert False

    @abstractmethod
    def items(self):
        assert False

    @abstractmethod
    def __getitem__(self, key):
        assert False


class ModeKeyedModel(collections.OrderedDict, Submodel):
    def Add(self, name, value_obj, context):
        if name not in self:
            self[name] = {}

        if isinstance(value_obj, dict):
            for mode in value_obj:
                value = self._CreateValue(value_obj[mode])
                if mode == 'default':
                    mode = Modes.DEFAULT
                assert mode in Modes.ALL and mode not in self[name]
                self[name][mode] = value
        else:
            self[name][Modes.DEFAULT] = self._CreateValue(value_obj)
        return [StyleVariable(self.variable_type, name, value_obj, context)]

    # Returns the value that |name| will have in |mode|. Resolves to the default
    # mode's value if the a value for |mode| isn't specified. Always returns a
    # value.
    def Resolve(self, name, mode):
        if mode in self[name]:
            return self[name][mode]

        return self[name][Modes.DEFAULT]

    def Flatten(self, resolve_missing=False):
        '''Builds a name to variable dictionary for each mode.
        If |resolve_missing| is true, colors that aren't specified in |mode|
        will be resolved to their default mode value.'''
        flattened = {}
        for mode in Modes.ALL:
            variables = collections.OrderedDict()
            for name, mode_values in self.items():
                if resolve_missing:
                    variables[name] = self.Resolve(name, mode)
                else:
                    if mode in mode_values:
                        variables[name] = mode_values[mode]
            flattened[mode] = variables

        return flattened


class OpacityModel(ModeKeyedModel):
    '''A dictionary of opacity names to their values in each mode.
       e.g OpacityModel['disabled_opacity'][Modes.LIGHT] = Opacity(...)
    '''

    def __init__(self):
        self.variable_type = VariableType.OPACITY

    # Returns a float from 0-1 representing the concrete value of |opacity|.
    def ResolveOpacity(self, opacity, mode):
        if opacity.a != -1:
            return opacity

        return self.ResolveOpacity(self.Resolve(opacity.var, mode), mode)

    def _CreateValue(self, value):
        return Opacity(value)


class ColorModel(ModeKeyedModel):
    '''A dictionary of color names to their values in each mode.
       e.g ColorModel['blue'][Modes.LIGHT] = Color(...)
    '''

    def __init__(self, opacity_model):
        self.opacity_model = opacity_model
        self.variable_type = VariableType.COLOR

    def Add(self, name, value_obj, context):
        added = []
        # If a color has generate_per_mode set, a separate variable will be
        # created for each mode, suffixed by mode name.
        # (e.g my_color_light, my_color_debug)
        generate_per_mode = False

        # If a color has generate_inverted set, a |color_name|_inverted will be
        # generated which uses the dark color for light mode and vice versa.
        generate_inverted = False
        if isinstance(value_obj, dict):
            generate_per_mode = value_obj.pop('generate_per_mode', None)
            generate_inverted = value_obj.pop('generate_inverted', None)
        elif self._CreateValue(value_obj).blended_colors:
            # A blended color could evaluate to different colors in different
            # modes, so add it to all the modes.
            value_obj = {mode: value_obj for mode in Modes.ALL}

        generated_context = dict(context)
        generated_context['generated'] = True

        if generate_per_mode or generate_inverted:
            for mode, value in value_obj.items():
                per_mode_name = name + '_' + mode
                added += ModeKeyedModel.Add(self, per_mode_name, value,
                                            generated_context)
                value_obj[mode] = '$' + per_mode_name
        if generate_inverted:
            if Modes.LIGHT not in value_obj or Modes.DARK not in value_obj:
                raise ValueError(
                    'generate_inverted requires both dark and light modes to be'
                    ' set')
            added += ModeKeyedModel.Add(
                self, name + '_inverted', {
                    Modes.LIGHT: '$' + name + '_dark',
                    Modes.DARK: '$' + name + '_light'
                }, generated_context)

        added += ModeKeyedModel.Add(self, name, value_obj, context)
        return added

    # Returns a Color that is the final RGBA value for |name| in |mode|.
    def ResolveToRGBA(self, name, mode):
        return self._ResolveColorToRGBA(self.Resolve(name, mode), mode)

    # Returns a Color that is the final RGBA value for |color| in |mode|.
    def _ResolveColorToRGBA(self, color, mode):
        if color.var:
            return self.ResolveToRGBA(color.var, mode)

        if len(color.blended_colors) == 2:
            return self._BlendColors(color.blended_colors[0],
                                     color.blended_colors[1], mode)

        result = Color()
        assert color.opacity
        result.opacity = self.opacity_model.ResolveOpacity(color.opacity, mode)

        rgb = color
        if color.rgb_var:
            rgb = self.ResolveToRGBA(color.RGBVarToVar(), mode)

        (result.r, result.g, result.b) = (rgb.r, rgb.g, rgb.b)
        return result

    def _ResolveBlendedColors(self):
        # Calculate the final RGBA for all blended colors because the
        # generator's subclasses can't blend yet.
        temp_model = {}
        for name, value in self.items():
            for mode, color in value.items():
                if color.blended_colors:
                    assert len(color.blended_colors) == 2
                    if name not in temp_model:
                        temp_model[name] = {}
                    temp_model[name][mode] = self.ResolveToRGBA(name, mode)
        for name, value in temp_model.items():
            for mode, color in value.items():
                self[name][mode] = temp_model[name][mode]

    # Returns a Color that is the final RGBA value for |color_a| over |color_b|
    # in |mode|.
    def _BlendColors(self, color_a, color_b, mode):
        # TODO(b/206887565): Check for circular references.
        color_a_res = self._ResolveColorToRGBA(color_a, mode)
        (alpha_a, r_a, g_a, b_a) = (color_a_res.opacity.a, color_a_res.r,
                                    color_a_res.g, color_a_res.b)
        color_b_res = self._ResolveColorToRGBA(color_b, mode)
        (alpha_b, r_b, g_b, b_b) = (color_b_res.opacity.a, color_b_res.r,
                                    color_b_res.g, color_b_res.b)

        # Blend using the formula for "A over B" from
        # https://wikipedia.org/wiki/Alpha_compositing.
        alpha_out = alpha_a + (alpha_b * (1 - alpha_a))
        r_out = round(
            (r_a * alpha_a + r_b * alpha_b * (1 - alpha_a)) / alpha_out)
        g_out = round(
            (g_a * alpha_a + g_b * alpha_b * (1 - alpha_a)) / alpha_out)
        b_out = round(
            (b_a * alpha_a + b_b * alpha_b * (1 - alpha_a)) / alpha_out)

        result = Color()
        (result.r, result.g, result.b) = (r_out, g_out, b_out)
        result.opacity = Opacity(alpha_out)
        return result

    def _CreateValue(self, value):
        return Color(value)


class SimpleModel(collections.OrderedDict, Submodel):
    def __init__(self, variable_type, check_func=None):
        self.variable_type = variable_type
        self.check_func = check_func

    def Add(self, name, value_obj, context):
        if self.check_func:
            self.check_func(name, value_obj, context)
        self[name] = value_obj
        return [StyleVariable(self.variable_type, name, value_obj, context)]


class Model(object):
    def __init__(self):
        # A map of all variables to their |StyleVariable| object.
        self.variable_map = dict()

        # A map of |VariableType| to its underlying model.
        self.submodels = dict()

        self.opacities = OpacityModel()
        self.submodels[VariableType.OPACITY] = self.opacities

        self.colors = ColorModel(self.opacities)
        self.submodels[VariableType.COLOR] = self.colors

        self.untyped_css = SimpleModel(VariableType.UNTYPED_CSS)
        self.submodels[VariableType.UNTYPED_CSS] = self.untyped_css

        def CheckTypeFace(name, value_obj, context):
            assert value_obj['font_family']
            assert value_obj['font_size']
            assert value_obj['font_weight']
            assert value_obj['line_height']

        self.typefaces = SimpleModel(VariableType.TYPEFACE, CheckTypeFace)
        self.submodels[VariableType.TYPEFACE] = self.typefaces

        def CheckFontFamily(name, value_obj, context):
            assert name.startswith('font_family_')

        self.font_families = SimpleModel(VariableType.FONT_FAMILY,
                                         CheckFontFamily)
        self.submodels[VariableType.FONT_FAMILY] = self.font_families

    def Add(self, variable_type, name, value_obj, context):
        '''Adds a new variable to the submodel for |variable_type|.
        '''
        try:
            full_name = self.FullTokenName(name, context)
            added = self.submodels[variable_type].Add(full_name, value_obj,
                                                      context)
        except ValueError as err:
            raise ValueError(
                f'Error parsing {variable_type} "{full_name}": {value_obj}'
            ) from err

        for var in added:
            if var.name in self.variable_map:
                raise ValueError('Variable name "%s" is reused' % name)
            self.variable_map[var.name] = var

    def FullTokenName(self, name, context):
        namespace = context['token_namespace']
        if namespace:
            return f'{namespace}.{name}'
        return name

    def PostProcess(self, resolve_blended_colors=True):
        '''Called after all variables have been added to perform operations that
           require a complete worldview.
        '''
        if resolve_blended_colors:
            # Resolve blended colors after all the files are added because some
            # color dependencies are between different files.
            self.colors._ResolveBlendedColors()

        self.Validate()

    def Validate(self):
        colors = self.colors
        color_names = set(colors.keys())
        opacities = self.opacities
        opacity_names = set(opacities.keys())

        def CheckColorReference(name, referrer):
            if name == referrer:
                raise ValueError("{0} refers to itself".format(name))
            if name not in color_names:
                raise ValueError("Cannot find color %s referenced by %s" %
                                 (name, referrer))

        def CheckOpacityReference(name, referrer):
            if name == referrer:
                raise ValueError("{0} refers to itself".format(name))
            if name not in opacity_names:
                raise ValueError("Cannot find opacity %s referenced by %s" %
                                 (name, referrer))

        def CheckColor(color, name):
            if color.var:
                CheckColorReference(color.var, name)
            if color.rgb_var:
                CheckColorReference(color.RGBVarToVar(), name)
            if color.opacity and color.opacity.var:
                CheckOpacityReference(color.opacity.var, name)
            if color.blended_colors:
                assert len(color.blended_colors) == 2
                CheckColor(color.blended_colors[0], name)
                CheckColor(color.blended_colors[1], name)

        RESERVED_SUFFIXES = ['_' + s for s in Modes.ALL + ['rgb', 'inverted']]

        # Check all colors in all modes refer to colors that exist in the
        # default mode.
        for name, mode_values in colors.items():
            for suffix in RESERVED_SUFFIXES:
                if not self.variable_map[name].context.get(
                        'generated') and name.endswith(suffix):
                    raise ValueError(
                        'Variable name "%s" uses a reserved suffix: %s' %
                        (name, suffix))
            if Modes.DEFAULT not in mode_values:
                raise ValueError("Color %s not defined for default mode" %
                                 name)

            for mode, color in mode_values.items():
                CheckColor(color, name)

        for name, mode_values in opacities.items():
            for mode, opacity in mode_values.items():
                if opacity.var:
                    CheckOpacityReference(opacity.var, name)

        # TODO(b/206887565): Check for circular references.
