#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File:                Ampel-core/ampel/aux/filter/AbsLogicOperatorFilter.py
# License:             BSD-3-Clause
# Author:              valery brinnel <firstname.lastname@gmail.com>
# Date:                14.01.2020
# Last Modified Date:  18.06.2020
# Last Modified By:    valery brinnel <firstname.lastname@gmail.com>

from collections.abc import Sequence
from typing import Any, Generic

from ampel.abstract.AbsApplicable import AbsApplicable
from ampel.base.decorator import abstractmethod
from ampel.model.aux.FilterCriterion import FilterCriterion
from ampel.model.operator.AllOf import AllOf
from ampel.model.operator.FlatAnyOf import FlatAnyOf
from ampel.types import T


# mypy: disable-error-code = empty-body
class AbsLogicOperatorFilter(AbsApplicable, Generic[T], abstract=True):

	filters: FilterCriterion | FlatAnyOf[FilterCriterion] | AllOf[FilterCriterion]

	@staticmethod
	@abstractmethod
	def _apply_filter(args: Sequence[T], f: FilterCriterion) -> list[T]:
		...

	def apply(self, args: Sequence[T]) -> list[T]:

		if isinstance(self.filters, FilterCriterion):
			return self._apply_filter(args, self.filters)

		if isinstance(self.filters, AllOf):
			ret: Any = args
			for f in self.filters.all_of:
				ret = self._apply_filter(ret, f)
			return ret

		if isinstance(self.filters, FlatAnyOf):
			ret = []
			for f in self.filters.any_of:
				for el in self._apply_filter(args, f):
					if el not in ret:
						ret.append(el)
			return ret

		raise ValueError("Incorrect type provided for parameter 'filters'")
