
import logging
import operator
import os
import re

from repoman.modules.linechecks.base import InheritEclass
from repoman.modules.linechecks.config import LineChecksConfig
from repoman._portage import portage

# Avoid a circular import issue in py2.7
portage.proxy.lazyimport.lazyimport(globals(),
	'portage.module:Modules',
)

MODULES_PATH = os.path.dirname(__file__)
# initial development debug info
logging.debug("LineChecks module path: %s", MODULES_PATH)


class LineCheckController(object):
	'''Initializes and runs the LineCheck checks'''

	def __init__(self, repo_settings, linechecks):
		'''Class init

		@param repo_settings: RepoSettings instance
		'''
		self.repo_settings = repo_settings
		self.linechecks = linechecks
		self.config = LineChecksConfig(repo_settings)

		self.controller = Modules(path=MODULES_PATH, namepath="repoman.modules.linechecks")
		logging.debug("LineCheckController; module_names: %s", self.controller.module_names)

		self._constant_checks = None

		self._here_doc_re = re.compile(r'.*<<[-]?(\w+)\s*(>\s*\S+\s*)?$')
		self._ignore_comment_re = re.compile(r'^\s*#')
		self._continuation_re = re.compile(r'(\\)*$')

	def checks_init(self, experimental_inherit=False):
		'''Initialize the main variables

		@param experimental_inherit boolean
		'''
		if not experimental_inherit:
			# Emulate the old eprefixify.defined and inherit.autotools checks.
			self._eclass_info = self.config.eclass_info
		else:
			self._eclass_info = self.config.eclass_info_experimental_inherit

		self._constant_checks = []
		logging.debug("LineCheckController; modules: %s", self.linechecks)
		# Add in the pluggable modules
		for mod in self.linechecks:
			mod_class = self.controller.get_class(mod)
			logging.debug("LineCheckController; module_name: %s, class: %s", mod, mod_class.__name__)
			self._constant_checks.append(mod_class(self.config.errors))
		# Add in the InheritEclass checks
		logging.debug("LineCheckController; eclass_info.items(): %s", list(self.config.eclass_info))
		for k, kwargs in self.config.eclass_info.items():
			logging.debug("LineCheckController; k: %s, kwargs: %s", k, kwargs)
			self._constant_checks.append(
				InheritEclass(
					k,
					self.config.eclass_eapi_functions,
					self.config.errors,
					**kwargs
				)
			)


	def run_checks(self, contents, pkg):
		'''Run the configured linechecks

		@param contents: the ebjuild contents to check
		@param pkg: the package being checked
		'''
		if self._constant_checks is None:
			self.checks_init()
		checks = self._constant_checks
		here_doc_delim = None
		multiline = None

		for lc in checks:
			lc.new(pkg)

		multinum = 0
		for num, line in enumerate(contents):

			# Check if we're inside a here-document.
			if here_doc_delim is not None:
				if here_doc_delim.match(line):
					here_doc_delim = None
			if here_doc_delim is None:
				here_doc = self._here_doc_re.match(line)
				if here_doc is not None:
					here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1))
			if here_doc_delim is not None:
				continue

			# Unroll multiline escaped strings so that we can check things:
			# 	inherit foo bar \
			# 		moo \
			# 		cow
			# This will merge these lines like so:
			# 	inherit foo bar moo cow
			# A line ending with an even number of backslashes does not count,
			# because the last backslash is escaped. Therefore, search for an
			# odd number of backslashes.
			line_escaped = operator.sub(*self._continuation_re.search(line).span()) % 2 == 1
			if multiline:
				# Chop off the \ and \n bytes from the previous line.
				multiline = multiline[:-2] + line
				if not line_escaped:
					line = multiline
					num = multinum
					multiline = None
				else:
					continue
			else:
				if line_escaped:
					multinum = num
					multiline = line
					continue

			if not line.endswith("#nowarn\n"):
				# Finally we have a full line to parse.
				is_comment = self._ignore_comment_re.match(line) is not None
				for lc in checks:
					if is_comment and lc.ignore_comment:
						continue
					if lc.check_eapi(pkg.eapi):
						ignore = lc.ignore_line
						if not ignore or not ignore.match(line):
							e = lc.check(num, line)
							if e:
								yield lc.repoman_check_name, e % (num + 1)

		for lc in checks:
			i = lc.end()
			if i is not None:
				for e in i:
					yield lc.repoman_check_name, e
