"""
These meta-datasources operate on :class:`revscoring.Datasource`'s that
return `list`'s and apply a specific function to each item.

.. autoclass:: revscoring.datasources.meta.mappers.map

.. autoclass:: revscoring.datasources.meta.mappers.lower_case

.. autoclass:: revscoring.datasources.meta.mappers.abs
"""
from ..datasource import Datasource

absolute_value = abs


class map(Datasource):
    """
    Returns a :class:`revscoring.Datasource` that applies a function over
    a set of items generated by another datasource.

    :Parameters:
        apply : `func`
            A function to apply to each item generated by `items_datasource`
        items_datasource : :class:`revscoring.Datasource`
            A datasource that generates a list of some item
        name : `str`
            A name for the datasource.
    """
    def __init__(self, apply, items_datasource, name=None):
        self.apply = apply
        name = self._format_name(name, [apply, items_datasource])
        super().__init__(name, self.process, depends_on=[items_datasource])

    def process(self, items):
        return [self.apply(item) for item in items]


class lower_case(map):
    """
    Returns a :class:`revscoring.Datasource` that lower cases a list of `str`
    returned by another datasource.

    :Parameters:
        strs_datasource : :class:`revscoring.Datasource`
            A datasource that generates a list of `str`
        name : `str`
            A name for the datasource.
    """
    def __init__(self, strs_datasource, name=None):
        name = self._format_name(name, [strs_datasource])
        super().__init__(self.lower, strs_datasource, name=name)

    def lower(self, s):
        return s.lower()


class abs(map):
    """
    Returns a :class:`revscoring.Datasource` that converts a list of numeric
    values into a list of absolute numeric values.

    :Parameters:
        numbers_datasource : :class:`revscoring.Datasource`
            A datasource that generates a list of numeric values
        name : `str`
            A name for the datasource.
    """
    def __init__(self, numbers_datasource, name=None):
        super().__init__(absolute_value, numbers_datasource, name=name)
