import sys
import logging
import timeit
from functools import wraps
from collections.abc import Mapping, Callable
import warnings
from logging import PercentStyle


# default logging level used by Timer class
TIME_LEVEL = logging.DEBUG

# per-level format strings used by the default formatter
# (the level name is not printed for INFO and DEBUG messages)
DEFAULT_FORMATS = {
	"*": "%(levelname)s: %(message)s",
	"INFO": "%(message)s",
	"DEBUG": "%(message)s",
	}


class LevelFormatter(logging.Formatter):
	"""Log formatter with level-specific formatting.

	Formatter class which optionally takes a dict of logging levels to
	format strings, allowing to customise the log records appearance for
	specific levels.


	Attributes:
		fmt: A dictionary mapping logging levels to format strings.
			The ``*`` key identifies the default format string.
		datefmt: As per py:class:`logging.Formatter`
		style: As per py:class:`logging.Formatter`

	>>> import sys
	>>> handler = logging.StreamHandler(sys.stdout)
	>>> formatter = LevelFormatter(
	...     fmt={
	...         '*':     '[%(levelname)s] %(message)s',
	...         'DEBUG': '%(name)s [%(levelname)s] %(message)s',
	...         'INFO':  '%(message)s',
	...     })
	>>> handler.setFormatter(formatter)
	>>> log = logging.getLogger('test')
	>>> log.setLevel(logging.DEBUG)
	>>> log.addHandler(handler)
	>>> log.debug('this uses a custom format string')
	test [DEBUG] this uses a custom format string
	>>> log.info('this also uses a custom format string')
	this also uses a custom format string
	>>> log.warning("this one uses the default format string")
	[WARNING] this one uses the default format string
	"""

	def __init__(self, fmt=None, datefmt=None, style="%"):
		if style != '%':
			raise ValueError(
				"only '%' percent style is supported in both python 2 and 3")
		if fmt is None:
			fmt = DEFAULT_FORMATS
		if isinstance(fmt, str):
			default_format = fmt
			custom_formats = {}
		elif isinstance(fmt, Mapping):
			custom_formats = dict(fmt)
			default_format = custom_formats.pop("*", None)
		else:
			raise TypeError('fmt must be a str or a dict of str: %r' % fmt)
		super(LevelFormatter, self).__init__(default_format, datefmt)
		self.default_format = self._fmt
		self.custom_formats = {}
		for level, fmt in custom_formats.items():
			level = logging._checkLevel(level)
			self.custom_formats[level] = fmt

	def format(self, record):
		if self.custom_formats:
			fmt = self.custom_formats.get(record.levelno, self.default_format)
			if self._fmt != fmt:
				self._fmt = fmt
				# for python >= 3.2, _style needs to be set if _fmt changes
				if PercentStyle:
					self._style = PercentStyle(fmt)
		return super(LevelFormatter, self).format(record)


def configLogger(**kwargs):
	"""A more sophisticated logging system configuation manager.

	This is more or less the same as :py:func:`logging.basicConfig`,
	with some additional options and defaults.

	The default behaviour is to create a ``StreamHandler`` which writes to
	sys.stderr, set a formatter using the ``DEFAULT_FORMATS`` strings, and add
	the handler to the top-level library logger ("fontTools").

	A number of optional keyword arguments may be specified, which can alter
	the default behaviour.

	Args:

		logger: Specifies the logger name or a Logger instance to be
			configured. (Defaults to "fontTools" logger). Unlike ``basicConfig``,
			this function can be called multiple times to reconfigure a logger.
			If the logger or any of its children already exists before the call is
			made, they will be reset before the new configuration is applied.
		filename: Specifies that a ``FileHandler`` be created, using the
			specified filename, rather than a ``StreamHandler``.
		filemode: Specifies the mode to open the file, if filename is
			specified. (If filemode is unspecified, it defaults to ``a``).
		format: Use the specified format string for the handler. This
			argument also accepts a dictionary of format strings keyed by
			level name, to allow customising the records appearance for
			specific levels. The special ``'*'`` key is for 'any other' level.
		datefmt: Use the specified date/time format.
		level: Set the logger level to the specified level.
		stream: Use the specified stream to initialize the StreamHandler. Note
			that this argument is incompatible with ``filename`` - if both
			are present, ``stream`` is ignored.
		handlers: If specified, this should be an iterable of already created
			handlers, which will be added to the logger. Any handler in the
			list which does not have a formatter assigned will be assigned the
			formatter created in this function.
		filters: If specified, this should be an iterable of already created
			filters. If the ``handlers`` do not already have filters assigned,
			these filters will be added to them.
		propagate: All loggers have a ``propagate`` attribute which determines
			whether to continue searching for handlers up the logging hierarchy.
			If not provided, the "propagate" attribute will be set to ``False``.
	"""
	# using kwargs to enforce keyword-only arguments in py2.
	handlers = kwargs.pop("handlers", None)
	if handlers is None:
		if "stream" in kwargs and "filename" in kwargs:
			raise ValueError("'stream' and 'filename' should not be "
							 "specified together")
	else:
		if "stream" in kwargs or "filename" in kwargs:
			raise ValueError("'stream' or 'filename' should not be "
							 "specified together with 'handlers'")
	if handlers is None:
		filename = kwargs.pop("filename", None)
		mode = kwargs.pop("filemode", 'a')
		if filename:
			h = logging.FileHandler(filename, mode)
		else:
			stream = kwargs.pop("stream", None)
			h = logging.StreamHandler(stream)
		handlers = [h]
	# By default, the top-level library logger is configured.
	logger = kwargs.pop("logger", "fontTools")
	if not logger or isinstance(logger, str):
		# empty "" or None means the 'root' logger
		logger = logging.getLogger(logger)
	# before (re)configuring, reset named logger and its children (if exist)
	_resetExistingLoggers(parent=logger.name)
	# use DEFAULT_FORMATS if 'format' is None
	fs = kwargs.pop("format", None)
	dfs = kwargs.pop("datefmt", None)
	# XXX: '%' is the only format style supported on both py2 and 3
	style = kwargs.pop("style", '%')
	fmt = LevelFormatter(fs, dfs, style)
	filters = kwargs.pop("filters", [])
	for h in handlers:
		if h.formatter is None:
			h.setFormatter(fmt)
		if not h.filters:
			for f in filters:
				h.addFilter(f)
		logger.addHandler(h)
	if logger.name != "root":
		# stop searching up the hierarchy for handlers
		logger.propagate = kwargs.pop("propagate", False)
	# set a custom severity level
	level = kwargs.pop("level", None)
	if level is not None:
		logger.setLevel(level)
	if kwargs:
		keys = ', '.join(kwargs.keys())
		raise ValueError('Unrecognised argument(s): %s' % keys)


def _resetExistingLoggers(parent="root"):
	""" Reset the logger named 'parent' and all its children to their initial
	state, if they already exist in the current configuration.
	"""
	root = logging.root
	# get sorted list of all existing loggers
	existing = sorted(root.manager.loggerDict.keys())
	if parent == "root":
		# all the existing loggers are children of 'root'
		loggers_to_reset = [parent] + existing
	elif parent not in existing:
		# nothing to do
		return
	elif parent in existing:
		loggers_to_reset = [parent]
		# collect children, starting with the entry after parent name
		i = existing.index(parent) + 1
		prefixed = parent + "."
		pflen = len(prefixed)
		num_existing = len(existing)
		while i < num_existing:
			if existing[i][:pflen] == prefixed:
				loggers_to_reset.append(existing[i])
			i += 1
	for name in loggers_to_reset:
		if name == "root":
			root.setLevel(logging.WARNING)
			for h in root.handlers[:]:
				root.removeHandler(h)
			for f in root.filters[:]:
				root.removeFilters(f)
			root.disabled = False
		else:
			logger = root.manager.loggerDict[name]
			logger.level = logging.NOTSET
			logger.handlers = []
			logger.filters = []
			logger.propagate = True
			logger.disabled = False


class Timer(object):
	""" Keeps track of overall time and split/lap times.

	>>> import time
	>>> timer = Timer()
	>>> time.sleep(0.01)
	>>> print("First lap:", timer.split())
	First lap: ...
	>>> time.sleep(0.02)
	>>> print("Second lap:", timer.split())
	Second lap: ...
	>>> print("Overall time:", timer.time())
	Overall time: ...

	Can be used as a context manager inside with-statements.

	>>> with Timer() as t:
	...     time.sleep(0.01)
	>>> print("%0.3f seconds" % t.elapsed)
	0... seconds

	If initialised with a logger, it can log the elapsed time automatically
	upon exiting the with-statement.

	>>> import logging
	>>> log = logging.getLogger("my-fancy-timer-logger")
	>>> configLogger(logger=log, level="DEBUG", format="%(message)s", stream=sys.stdout)
	>>> with Timer(log, 'do something'):
	...     time.sleep(0.01)
	Took ... to do something

	The same Timer instance, holding a reference to a logger, can be reused
	in multiple with-statements, optionally with different messages or levels.

	>>> timer = Timer(log)
	>>> with timer():
	...     time.sleep(0.01)
	elapsed time: ...s
	>>> with timer('redo it', level=logging.INFO):
	...     time.sleep(0.02)
	Took ... to redo it

	It can also be used as a function decorator to log the time elapsed to run
	the decorated function.

	>>> @timer()
	... def test1():
	...    time.sleep(0.01)
	>>> @timer('run test 2', level=logging.INFO)
	... def test2():
	...    time.sleep(0.02)
	>>> test1()
	Took ... to run 'test1'
	>>> test2()
	Took ... to run test 2
	"""

	# timeit.default_timer choses the most accurate clock for each platform
	_time = timeit.default_timer
	default_msg = "elapsed time: %(time).3fs"
	default_format = "Took %(time).3fs to %(msg)s"

	def __init__(self, logger=None, msg=None, level=None, start=None):
		self.reset(start)
		if logger is None:
			for arg in ('msg', 'level'):
				if locals().get(arg) is not None:
					raise ValueError(
						"'%s' can't be specified without a 'logger'" % arg)
		self.logger = logger
		self.level = level if level is not None else TIME_LEVEL
		self.msg = msg

	def reset(self, start=None):
		""" Reset timer to 'start_time' or the current time. """
		if start is None:
			self.start = self._time()
		else:
			self.start = start
		self.last = self.start
		self.elapsed = 0.0

	def time(self):
		""" Return the overall time (in seconds) since the timer started. """
		return self._time() - self.start

	def split(self):
		""" Split and return the lap time (in seconds) in between splits. """
		current = self._time()
		self.elapsed = current - self.last
		self.last = current
		return self.elapsed

	def formatTime(self, msg, time):
		""" Format 'time' value in 'msg' and return formatted string.
		If 'msg' contains a '%(time)' format string, try to use that.
		Otherwise, use the predefined 'default_format'.
		If 'msg' is empty or None, fall back to 'default_msg'.
		"""
		if not msg:
			msg = self.default_msg
		if msg.find("%(time)") < 0:
			msg = self.default_format % {"msg": msg, "time": time}
		else:
			try:
				msg = msg % {"time": time}
			except (KeyError, ValueError):
				pass  # skip if the format string is malformed
		return msg

	def __enter__(self):
		""" Start a new lap """
		self.last = self._time()
		self.elapsed = 0.0
		return self

	def __exit__(self, exc_type, exc_value, traceback):
		""" End the current lap. If timer has a logger, log the time elapsed,
		using the format string in self.msg (or the default one).
		"""
		time = self.split()
		if self.logger is None or exc_type:
			# if there's no logger attached, or if any exception occurred in
			# the with-statement, exit without logging the time
			return
		message = self.formatTime(self.msg, time)
		# Allow log handlers to see the individual parts to facilitate things
		# like a server accumulating aggregate stats.
		msg_parts = { 'msg': self.msg, 'time': time }
		self.logger.log(self.level, message, msg_parts)

	def __call__(self, func_or_msg=None, **kwargs):
		""" If the first argument is a function, return a decorator which runs
		the wrapped function inside Timer's context manager.
		Otherwise, treat the first argument as a 'msg' string and return an updated
		Timer instance, referencing the same logger.
		A 'level' keyword can also be passed to override self.level.
		"""
		if isinstance(func_or_msg, Callable):
			func = func_or_msg
			# use the function name when no explicit 'msg' is provided
			if not self.msg:
				self.msg = "run '%s'" % func.__name__

			@wraps(func)
			def wrapper(*args, **kwds):
				with self:
					return func(*args, **kwds)
			return wrapper
		else:
			msg = func_or_msg or kwargs.get("msg")
			level = kwargs.get("level", self.level)
			return self.__class__(self.logger, msg, level)

	def __float__(self):
		return self.elapsed

	def __int__(self):
		return int(self.elapsed)

	def __str__(self):
		return "%.3f" % self.elapsed


class ChannelsFilter(logging.Filter):
	"""Provides a hierarchical filter for log entries based on channel names.

	Filters out records emitted from a list of enabled channel names,
	including their children. It works the same as the ``logging.Filter``
	class, but allows the user to specify multiple channel names.

	>>> import sys
	>>> handler = logging.StreamHandler(sys.stdout)
	>>> handler.setFormatter(logging.Formatter("%(message)s"))
	>>> filter = ChannelsFilter("A.B", "C.D")
	>>> handler.addFilter(filter)
	>>> root = logging.getLogger()
	>>> root.addHandler(handler)
	>>> root.setLevel(level=logging.DEBUG)
	>>> logging.getLogger('A.B').debug('this record passes through')
	this record passes through
	>>> logging.getLogger('A.B.C').debug('records from children also pass')
	records from children also pass
	>>> logging.getLogger('C.D').debug('this one as well')
	this one as well
	>>> logging.getLogger('A.B.').debug('also this one')
	also this one
	>>> logging.getLogger('A.F').debug('but this one does not!')
	>>> logging.getLogger('C.DE').debug('neither this one!')
	"""

	def __init__(self, *names):
		self.names = names
		self.num = len(names)
		self.lengths = {n: len(n) for n in names}

	def filter(self, record):
		if self.num == 0:
			return True
		for name in self.names:
			nlen = self.lengths[name]
			if name == record.name:
				return True
			elif (record.name.find(name, 0, nlen) == 0
					and record.name[nlen] == "."):
				return True
		return False


class CapturingLogHandler(logging.Handler):
	def __init__(self, logger, level):
		super(CapturingLogHandler, self).__init__(level=level)
		self.records = []
		if isinstance(logger, str):
			self.logger = logging.getLogger(logger)
		else:
			self.logger = logger

	def __enter__(self):
		self.original_disabled = self.logger.disabled
		self.original_level = self.logger.level
		self.original_propagate = self.logger.propagate

		self.logger.addHandler(self)
		self.logger.setLevel(self.level)
		self.logger.disabled = False
		self.logger.propagate = False

		return self

	def __exit__(self, type, value, traceback):
		self.logger.removeHandler(self)
		self.logger.setLevel(self.original_level)
		self.logger.disabled = self.original_disabled
		self.logger.propagate = self.original_propagate

		return self

	def emit(self, record):
		self.records.append(record)

	def assertRegex(self, regexp, msg=None):
		import re
		pattern = re.compile(regexp)
		for r in self.records:
			if pattern.search(r.getMessage()):
				return True
		if msg is None:
			msg = "Pattern '%s' not found in logger records" % regexp
		assert 0, msg


class LogMixin(object):
	""" Mixin class that adds logging functionality to another class.

	You can define a new class that subclasses from ``LogMixin`` as well as
	other base classes through multiple inheritance.
	All instances of that class will have a ``log`` property that returns
	a ``logging.Logger`` named after their respective ``<module>.<class>``.

	For example:

	>>> class BaseClass(object):
	...     pass
	>>> class MyClass(LogMixin, BaseClass):
	...     pass
	>>> a = MyClass()
	>>> isinstance(a.log, logging.Logger)
	True
	>>> print(a.log.name)
	fontTools.misc.loggingTools.MyClass
	>>> class AnotherClass(MyClass):
	...     pass
	>>> b = AnotherClass()
	>>> isinstance(b.log, logging.Logger)
	True
	>>> print(b.log.name)
	fontTools.misc.loggingTools.AnotherClass
	"""

	@property
	def log(self):
		if not hasattr(self, "_log"):
			name = ".".join(
				(self.__class__.__module__, self.__class__.__name__)
			)
			self._log = logging.getLogger(name)
		return self._log


def deprecateArgument(name, msg, category=UserWarning):
	""" Raise a warning about deprecated function argument 'name'. """
	warnings.warn(
		"%r is deprecated; %s" % (name, msg), category=category, stacklevel=3)


def deprecateFunction(msg, category=UserWarning):
	""" Decorator to raise a warning when a deprecated function is called. """
	def decorator(func):
		@wraps(func)
		def wrapper(*args, **kwargs):
			warnings.warn(
				"%r is deprecated; %s" % (func.__name__, msg),
				category=category, stacklevel=2)
			return func(*args, **kwargs)
		return wrapper
	return decorator


if __name__ == "__main__":
	import doctest
	sys.exit(doctest.testmod(optionflags=doctest.ELLIPSIS).failed)
