# Copyright [2021] [Red Hat, Inc.]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import re


class Selector(object):

    equality_based_operators = ('==', '!=', '=')

    def __init__(self, data):
        self._operator = None
        self._data = None
        if not self.parse_set_based_requirement(data):
            no_whitespace_data = data.replace(" ", "")
            for op in self.equality_based_operators:
                idx = no_whitespace_data.find(op)
                if idx != -1:
                    self._operator = "in" if op == '==' or op == '=' else "notin"
                    self._key = no_whitespace_data[0:idx]
                    self._data = [no_whitespace_data[idx + len(op):]]
                    break

    def parse_set_based_requirement(self, data):
        m = re.match(r'( *)([a-z0-9A-Z][a-z0-9A-Z\._-]*[a-z0-9A-Z])( +)(notin|in)( +)\((.*)\)( *)', data)
        if m:
            self._set_based_requirement = True
            self._key = m.group(2)
            self._operator = m.group(4)
            self._data = [x.replace(' ', '') for x in m.group(6).split(',') if x != '']
            return True
        elif all(x not in data for x in self.equality_based_operators):
            self._key = data.rstrip(" ").lstrip(" ")
            if self._key.startswith("!"):
                self._key = self._key[1:].lstrip(" ")
                self._operator = "!"
            return True
        return False

    def isMatch(self, labels):
        if self._operator == "in":
            return self._key in labels and labels.get(self._key) in self._data
        elif self._operator == "notin":
            return self._key not in labels or labels.get(self._key) not in self._data
        else:
            return self._key not in labels if self._operator == "!" else self._key in labels


class LabelSelectorFilter(object):

    def __init__(self, label_selectors):
        self.selectors = [Selector(data) for data in label_selectors]

    def isMatching(self, definition):
        if "metadata" not in definition or "labels" not in definition['metadata']:
            return False
        labels = definition['metadata']['labels']
        if not isinstance(labels, dict):
            return None
        return all(sel.isMatch(labels) for sel in self.selectors)
