# Copyright (C) 2020-2022 HERE Global B.V. and its affiliate(s).
# All rights reserved.
#
# This software and other materials contain proprietary information
# controlled by HERE and are protected by applicable copyright legislation.
# Any use and utilization of this software and other materials and
# disclosure to any third parties is conditional upon having a separate
# agreement with HERE for the access, use, utilization or disclosure of this
# software. In the absence of such agreement, the use of the software is not
# allowed.

"""
This module provides deprecation decorators and is for internal use only.
"""

import functools
import warnings


def _deprecate_remove_parameters(
    remove_params, since_version, end_version="future", use_new_params=[]
):
    """
    Decorator to deprecate & remove specified parameters
    in the decorated functions and methods
    without changing function definition or signature.

    :param remove_params: List of old parameters which going to be removed.
    :param since_version : Version when the deprecation notice period starts.
        For informational purpose in the warning text.
    :param end_version: The version where use of the deprecated parameters will raise an error.
        For informational purpose in the warning text.
    :param use_new_params: List of new parameters which are to be used in place
        of deprecated parameters.
    :return: kwargs dictionary of all the keyword args passed on the decorated function.
    """

    def _remove_params(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            _warn_deprecated_params(
                remove_params, since_version, end_version, use_new_params, kwargs
            )
            return func(*args, **kwargs)

        return wrapper

    return _remove_params


def _warn_deprecated_params(remove_params, since_version, end_version, use_new_params, kwargs):
    """For the decorator remove_parameters(),
        raises warnings about deprecated parameters.

    :param remove_params: List of old parameters which going to be removed.
    :param since_version : Version when the deprecation notice period starts.
        For informational purpose in the warning text.
    :param end_version: The version where use of the deprecated parameters will raise an error.
        For informational purpose in the warning text.
    :param use_new_params: List of new parameters which are to be used in place
        of deprecated parameters.
    :param kwargs: Dictionary of all the keyword args passed on the decorated function.
    """
    used_deprecated_params = set(kwargs).intersection(remove_params)
    for deprecated_param in used_deprecated_params:
        param_deprecation_msg = (
            'The parameter "{}" is deprecated since {} and '
            "will be removed in {} release.".format(deprecated_param, since_version, end_version)
        )
        if use_new_params:
            msg = 'Use parameters - "{}" instead. '.format(", ".join(use_new_params))
            param_deprecation_msg = msg + param_deprecation_msg
        warnings.filterwarnings("always", message=param_deprecation_msg)
        warnings.warn(category=DeprecationWarning, message=param_deprecation_msg, stacklevel=3)
