# -*- coding: utf-8 -*-
# author: 王树根
# email: wangshugen@ict.ac.cn
# date: 2018/11/9 14:36
from contextlib import contextmanager
from threading import Thread


def deprecated(new_fn=None, version='0.7'):
  """
  标记为弃用 decorator
  :param new_fn: 新的替代函数
  :param version: 被移除版本
  :return 包装函数
  """
  if new_fn is not None:
    assert callable(new_fn)

  def function_wrapper(fn):
    assert callable(fn)

    def wrapper(*args, **kwargs):
      if version is None:
        future = 'the future'
      else:
        future = 'version {}'.format(str(version))

      params = {
        'fn_module': fn.__module__,
        'fn_name': fn.__name__,
        'future': future
      }
      fmts = list(['\n', 'Deprecated warning!\n'])
      fmts.append((
        '  some of your code are using deprecated function: \n'
      ))
      fmts.append((
        '    [{fn_name}] from [{fn_module}].\n'
      ))
      fmts.append((
        '  the deprecated will be removed in {future}.\n'
      ))

      if new_fn is not None:
        params['new_fn_module'] = new_fn.__module__
        params['new_fn_name'] = new_fn.__name__
        fmts.append((
          '  use [{new_fn_name}] from [{new_fn_module}] instead.'
          ''))

      import warnings
      message = ''.join(fmts)
      warnings.warn(message.format(**params))

      return fn(*args, **kwargs)

    return wrapper

  return function_wrapper


def async_call(daemon=False, name=None):
  """
  异步调用 decorator
  :param daemon: 是否为守护进程
  :param name: 线程名称
  :return 包装函数
  """

  def function_wrapper(fn):
    """
    函数修饰器
    :param fn: 被调用函数
    """
    assert callable(fn)

    def wrapper(*args, **kwargs):
      t = Thread(target=fn, args=args, kwargs=kwargs)
      t.setDaemon(daemon)
      if name is not None:
        t.setName(name)
      t.start()

    return wrapper

  return function_wrapper


@contextmanager
def none_context():
  yield
