# -*- encoding: utf-8 -*-

from inspect import getfullargspec
from typing import Callable
from typing import Dict


class KeywordArgumentsMapper(object):
    def __init__(self, **kwargs_changes: Dict[str, Callable]):
        for oldkw, mapper in kwargs_changes.items():
            assert isinstance(oldkw, str)
            assert callable(mapper)
        self.kwargs_changes = kwargs_changes

    def __call__(self, c):
        return KeywordArgumentsMapperConfigured(c, **self.kwargs_changes)


class KeywordArgumentsMapperConfigured(object):  # Don't instantiate this class manually
    def __init__(self, clb: Callable, **kwargs_changes: Dict[str, Callable]):
        self.kwargs_changes = kwargs_changes
        self.callback = clb
    
    def __call__(self, *args, **kwargs):
        newkwargs = kwargs.copy()
        for kw, mapper in self.kwargs_changes.items():
            newkwargs[kw] = mapper(**{
                k: kwargs[k]
                for k in getfullargspec(mapper).args
            })
        return self.callback(*args, **newkwargs)