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

from collections.abc import Iterable, Iterator, Sequence

from ampel.base.AmpelABC import AmpelABC
from ampel.base.decorator import abstractmethod
from ampel.core.ContextUnit import ContextUnit
from ampel.core.DataLoader import DataLoader
from ampel.log.AmpelLogger import AmpelLogger
from ampel.model.operator.AllOf import AllOf
from ampel.model.operator.AnyOf import AnyOf
from ampel.model.operator.OneOf import OneOf
from ampel.model.t3.LoaderDirective import LoaderDirective
from ampel.struct.AmpelBuffer import AmpelBuffer
from ampel.types import ChannelId, StockId, StrictIterable, Traceless


# Data loaders need access to the ampel db (and hence inherits ContextUnit)
class AbsT3Loader(AmpelABC, ContextUnit, abstract=True):
	"""
	Base class for loading documents associated with a set of stocks.
	"""

	logger: Traceless[AmpelLogger]

	#: Specification of documents to load. If these are supplied as strings,
	#: they will be resolved by retrieving the corresponding alias from the
	#: Ampel config.
	directives: Sequence[LoaderDirective]

	#: Channels to load documents for
	channel: None | ChannelId | AnyOf[ChannelId] | AllOf[ChannelId] | OneOf[ChannelId]


	def __init__(self, **kwargs) -> None:

		# Note: 'directives' in kwargs can contain strings which will be
		# resolved by retrieving the associated alias from the ampel config
		directives: list[dict] = []

		# Resolve directive aliases
		for el in kwargs.get('directives', []):
			if isinstance(el, str):
				d = kwargs['context'].config.get(f"alias.t3.%{el}", dict)
				if d: # mypy does not yet support type inference using the walrus operator
					directives.append(d)
				else:
					raise ValueError(f"LoaderDirective alias '{el}' not found in ampel config")
			else:
				directives.append(el)

		kwargs['directives'] = tuple(directives)

		# No need to save context as instance variable
		super().__init__(**kwargs)

		self.data_loader = DataLoader(self.context)


	@abstractmethod
	def load(self,
		stock_ids: StockId | Iterator[StockId] | StrictIterable[StockId]
	) -> Iterable[AmpelBuffer]:
		""" Load documents (collection Ampel_data) for the selected stocks """
		...
