#!/usr/bin/env python3
#
#  Copyright (C) 2016 Codethink Limited
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>

import re

from ._exceptions import LoadError, LoadErrorReason
from . import _yaml

# Variables are allowed to have dashes here
#
_VARIABLE_MATCH = r'\%\{([a-zA-Z][a-zA-Z0-9_-]*)\}'


# The Variables helper object will resolve the variable references in
# the given dictionary, expecting that any dictionary values which contain
# variable references can be resolved from the same dictionary.
#
# Each Element creates its own Variables instance to track the configured
# variable settings for the element.
#
# Args:
#     node (dict): A node loaded and composited with yaml tools
#
# Raises:
#     LoadError, if unresolved variables occur.
#
class Variables():

    def __init__(self, node):

        self.original = node
        self.variables = self._resolve(node)

    # subst():
    #
    # Substitutes any variables in 'string' and returns the result.
    #
    # Args:
    #    (string): The string to substitute
    #
    # Returns:
    #    (string): The new string with any substitutions made
    #
    # Raises:
    #    LoadError, if the string contains unresolved variable references.
    #
    def subst(self, string):
        substitute, unmatched = self._subst(string, self.variables)
        unmatched = list(set(unmatched))
        if unmatched:
            if len(unmatched) == 1:
                message = "Unresolved variable '{var}'".format(var=unmatched[0])
            else:
                message = "Unresolved variables: "
                for unmatch in unmatched:
                    if unmatched.index(unmatch) > 0:
                        message += ', '
                    message += unmatch

            raise LoadError(LoadErrorReason.UNRESOLVED_VARIABLE, message)

        return substitute

    def _subst(self, string, variables):

        def subst_callback(match):
            nonlocal variables
            nonlocal unmatched

            token = match.group(0)
            varname = match.group(1)

            value = _yaml.node_get(variables, str, varname, default_value=None)
            if value is not None:
                # We have to check if the inner string has variables
                # and return unmatches for those
                unmatched += re.findall(_VARIABLE_MATCH, value)
            else:
                # Return unmodified token
                unmatched += [varname]
                value = token

            return value

        unmatched = []
        replacement = re.sub(_VARIABLE_MATCH, subst_callback, string)

        return (replacement, unmatched)

    # Variable resolving code
    #
    # Here we substitute variables for values (resolve variables) repeatedly
    # in a dictionary, each time creating a new dictionary until there is no
    # more unresolved variables to resolve, or, until resolving further no
    # longer resolves anything, in which case we throw an exception.
    def _resolve(self, node):
        variables = node

        # Special case, if notparallel is specified in the variables for this
        # element, then override max-jobs to be 1.
        # Initialize it as a string as all variables are processed as strings.
        #
        if _yaml.node_get(variables, bool, 'notparallel', default_value=False):
            variables['max-jobs'] = str(1)

        # Resolve the dictionary once, reporting the new dictionary with things
        # substituted in it, and reporting unmatched tokens.
        #
        def resolve_one(variables):
            unmatched = []
            resolved = {}

            for key, value in _yaml.node_items(variables):

                # Ensure stringness of the value before substitution
                value = _yaml.node_get(variables, str, key)

                resolved_var, item_unmatched = self._subst(value, variables)
                resolved[key] = resolved_var
                unmatched += item_unmatched

            # Carry over provenance
            resolved[_yaml.PROVENANCE_KEY] = variables[_yaml.PROVENANCE_KEY]
            return (resolved, unmatched)

        # Resolve it until it's resolved or broken
        #
        resolved = variables
        unmatched = ['dummy']
        last_unmatched = ['dummy']
        while unmatched:
            resolved, unmatched = resolve_one(resolved)

            # Lists of strings can be compared like this
            if unmatched == last_unmatched:
                # We've got the same result twice without matching everything,
                # something is undeclared or cyclic, compose a summary.
                #
                summary = ''
                for unmatch in set(unmatched):
                    for var, provenance in self._find_references(unmatch):
                        line = "  unresolved variable '{unmatched}' in declaration of '{variable}' at: {provenance}\n"
                        summary += line.format(unmatched=unmatch, variable=var, provenance=provenance)

                raise LoadError(LoadErrorReason.UNRESOLVED_VARIABLE,
                                "Failed to resolve one or more variable:\n{}".format(summary))

            last_unmatched = unmatched

        return resolved

    # Helper function to fetch information about the node referring to a variable
    #
    def _find_references(self, varname):
        fullname = '%{' + varname + '}'
        for key, value in _yaml.node_items(self.original):
            if fullname in value:
                provenance = _yaml.node_get_provenance(self.original, key)
                yield (key, provenance)
