# elog/__init__.py - elog core functions
# Copyright 2006-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

import sys

import portage
portage.proxy.lazyimport.lazyimport(globals(),
	'portage.util:writemsg',
)

from portage.const import EBUILD_PHASES
from portage.exception import AlarmSignal, PortageException
from portage.process import atexit_register
from portage.elog.messages import collect_ebuild_messages, collect_messages
from portage.elog.filtering import filter_loglevels
from portage.localization import _
from portage import os

def _preload_elog_modules(settings):
	logsystems = settings.get("PORTAGE_ELOG_SYSTEM", "").split()
	for s in logsystems:
		# allow per module overrides of PORTAGE_ELOG_CLASSES
		if ":" in s:
			s, levels = s.split(":", 1)
			levels = levels.split(",")
		# - is nicer than _ for module names, so allow people to use it.
		s = s.replace("-", "_")
		try:
			_load_mod("portage.elog.mod_" + s)
		except ImportError:
			pass

def _merge_logentries(a, b):
	rValue = {}
	phases = set(a)
	phases.update(b)
	for p in phases:
		merged_msgs = []
		rValue[p] = merged_msgs
		for d in a, b:
			msgs = d.get(p)
			if msgs:
				merged_msgs.extend(msgs)
	return rValue

def _combine_logentries(logentries):
	# generate a single string with all log messages
	rValue = []
	for phase in EBUILD_PHASES:
		if not phase in logentries:
			continue
		previous_type = None
		for msgtype, msgcontent in logentries[phase]:
			if previous_type != msgtype:
				previous_type = msgtype
				rValue.append("%s: %s" % (msgtype, phase))
			if isinstance(msgcontent, str):
				rValue.append(msgcontent.rstrip("\n"))
			else:
				for line in msgcontent:
					rValue.append(line.rstrip("\n"))
	if rValue:
		rValue.append("")
	return "\n".join(rValue)

_elog_mod_imports = {}
def _load_mod(name):
	global _elog_mod_imports
	m = _elog_mod_imports.get(name)
	if m is None:
		m = __import__(name)
		for comp in name.split(".")[1:]:
			m = getattr(m, comp)
		_elog_mod_imports[name] = m
	return m

_elog_listeners = []
def add_listener(listener):
	'''
	Listeners should accept four arguments: settings, key, logentries and logtext
	'''
	_elog_listeners.append(listener)

def remove_listener(listener):
	'''
	Remove previously added listener
	'''
	_elog_listeners.remove(listener)

_elog_atexit_handlers = []

def elog_process(cpv, mysettings, phasefilter=None):
	global _elog_atexit_handlers

	logsystems = mysettings.get("PORTAGE_ELOG_SYSTEM","").split()
	for s in logsystems:
		# allow per module overrides of PORTAGE_ELOG_CLASSES
		if ":" in s:
			s, levels = s.split(":", 1)
			levels = levels.split(",")
		# - is nicer than _ for module names, so allow people to use it.
		s = s.replace("-", "_")
		try:
			_load_mod("portage.elog.mod_" + s)
		except ImportError:
			pass

	if "T" in mysettings:
		ebuild_logentries = collect_ebuild_messages(
			os.path.join(mysettings["T"], "logging"))
	else:
		# A build dir isn't necessarily required since the messages.e*
		# functions allow messages to be generated in-memory.
		ebuild_logentries = {}
	all_logentries = collect_messages(key=cpv, phasefilter=phasefilter)
	if cpv in all_logentries:
		# Messages generated by the python elog implementation are assumed
		# to come first. For example, this ensures correct order for einfo
		# messages that are generated prior to the setup phase.
		all_logentries[cpv] = \
			_merge_logentries(all_logentries[cpv], ebuild_logentries)
	else:
		all_logentries[cpv] = ebuild_logentries

	my_elog_classes = set(mysettings.get("PORTAGE_ELOG_CLASSES", "").split())
	logsystems = {}
	for token in mysettings.get("PORTAGE_ELOG_SYSTEM", "").split():
		if ":" in token:
			s, levels = token.split(":", 1)
			levels = levels.split(",")
		else:
			s = token
			levels = ()
		levels_set = logsystems.get(s)
		if levels_set is None:
			levels_set = set()
			logsystems[s] = levels_set
		levels_set.update(levels)

	for key in all_logentries:
		default_logentries = filter_loglevels(all_logentries[key], my_elog_classes)

		# in case the filters matched all messages and no module overrides exist
		if len(default_logentries) == 0 and (not ":" in mysettings.get("PORTAGE_ELOG_SYSTEM", "")):
			continue

		default_fulllog = _combine_logentries(default_logentries)

		# call listeners
		for listener in _elog_listeners:
			listener(mysettings, str(key), default_logentries, default_fulllog)

		# pass the processing to the individual modules
		for s, levels in logsystems.items():
			# allow per module overrides of PORTAGE_ELOG_CLASSES
			if levels:
				mod_logentries = filter_loglevels(all_logentries[key], levels)
				mod_fulllog = _combine_logentries(mod_logentries)
			else:
				mod_logentries = default_logentries
				mod_fulllog = default_fulllog
			if len(mod_logentries) == 0:
				continue
			# - is nicer than _ for module names, so allow people to use it.
			s = s.replace("-", "_")
			try:
				m = _load_mod("portage.elog.mod_" + s)
				# Timeout after one minute (in case something like the mail
				# module gets hung).
				try:
					AlarmSignal.register(60)
					m.process(mysettings, str(key), mod_logentries, mod_fulllog)
				finally:
					AlarmSignal.unregister()
				if hasattr(m, "finalize") and not m.finalize in _elog_atexit_handlers:
					_elog_atexit_handlers.append(m.finalize)
					atexit_register(m.finalize)
			except (ImportError, AttributeError) as e:
				writemsg(_("!!! Error while importing logging modules "
					"while loading \"mod_%s\":\n") % str(s))
				writemsg("%s\n" % str(e), noiselevel=-1)
			except AlarmSignal:
				writemsg("Timeout in elog_process for system '%s'\n" % s,
					noiselevel=-1)
			except PortageException as e:
				writemsg("%s\n" % str(e), noiselevel=-1)
