#
# Copyright 2018 Russell Smiley
#
# This file is part of package-manifest.
#
# package-manifest is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# package-manifest 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with package-manifest.  If not, see <http://www.gnu.org/licenses/>.
#

import fnmatch
import re

from ..path.path import PathOperation
from ..yamlParser import \
    Files, \
    YamlNotFound


def applyGlobalInclusions( pathNames, inclusions ) :
    """
    Apply unix glob wildcard expressions to select items from an iterable of file names (basename). The wildcard is applied
    "globally".

    eg.
      "*.py" implies "select *.py files anywhere in the root directory and it's subdirectories, recursively".

    :param pathNames: path names to be filtered expressed relative to the root directory of the package-manifest.
    :param inclusions: include patterns

    :return: set of path names after inclusions have been applied.
    """
    previousNames = set()
    for thisInclude in inclusions :
        for thisName in pathNames :
            regularExpression = fnmatch.translate( thisInclude ) + '$'
            if re.search( regularExpression, thisName ) is not None :
                previousNames.add( thisName )

    return previousNames


class Include( PathOperation ) :
    __yamlKey = 'global-include'


    def __init__( self, includePattern ) :
        self.includePattern = includePattern


    def apply( self, originalPathNames, currentPathNames ) :
        assert all( [ x in originalPathNames for x in currentPathNames ] )

        includedNames = applyGlobalInclusions( originalPathNames, [ self.includePattern ] )
        modifiedNames = currentPathNames | includedNames

        return modifiedNames


    @classmethod
    def from_yamlData( cls, yamlData ) :
        if yamlData is None :
            raise YamlNotFound( 'yamlData is None' )
        elif Include.__yamlKey not in yamlData :
            raise YamlNotFound( '{1} not found in yaml data, {0}'.format( yamlData, Include.__yamlKey ) )
        else :
            try :
                filePatterns = Files.from_yamlData( yamlData[ Include.__yamlKey ] )

                result = list()
                for thisPattern in filePatterns.patterns :
                    result.append( cls( thisPattern ) )
            except YamlNotFound as e :
                raise YamlNotFound( '{1} must use files directive, {0}'.format( yamlData, Include.__yamlKey ) ) from e

        return result
