# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import unicode_literals

import errno
import io
import re
import stat
import sys
import warnings

from portage import os
from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
import portage
portage.proxy.lazyimport.lazyimport(globals(),
	'portage.dep:Atom,dep_getkey,isvalidatom,match_from_list',
	'portage.util:ConfigProtect,new_protect_filename,' + \
		'normalize_path,write_atomic,writemsg',
	'portage.versions:_get_slot_re',
)

from portage.const import USER_CONFIG_PATH, VCS_DIRS
from portage.eapi import _get_eapi_attrs
from portage.exception import DirectoryNotFound, InvalidAtom, PortageException
from portage.localization import _

if sys.hexversion >= 0x3000000:
	long = int
	_unicode = str
else:
	_unicode = unicode

ignored_dbentries = ("CONTENTS", "environment.bz2")

def update_dbentry(update_cmd, mycontent, eapi=None, parent=None):

	if parent is not None:
		eapi = parent.eapi

	if update_cmd[0] == "move":
		old_value = _unicode(update_cmd[1])
		new_value = _unicode(update_cmd[2])

		# Use isvalidatom() to check if this move is valid for the
		# EAPI (characters allowed in package names may vary).
		if old_value in mycontent and isvalidatom(new_value, eapi=eapi):
			# this split preserves existing whitespace
			split_content = re.split(r'(\s+)', mycontent)
			modified = False
			for i, token in enumerate(split_content):
				if old_value not in token:
					continue
				try:
					atom = Atom(token, eapi=eapi)
				except InvalidAtom:
					continue
				if atom.cp != old_value:
					continue

				new_atom = Atom(token.replace(old_value, new_value, 1),
					eapi=eapi)

				# Avoid creating self-blockers for bug #367215.
				if new_atom.blocker and parent is not None and \
					parent.cp == new_atom.cp and \
					match_from_list(new_atom, [parent]):
					continue

				split_content[i] = _unicode(new_atom)
				modified = True

			if modified:
				mycontent = "".join(split_content)

	elif update_cmd[0] == "slotmove" and update_cmd[1].operator is None:
		orig_atom, origslot, newslot = update_cmd[1:]
		orig_cp = orig_atom.cp

		# We don't support versioned slotmove atoms here, since it can be
		# difficult to determine if the version constraints really match
		# the atoms that we're trying to update.
		if orig_atom.version is None and orig_cp in mycontent:
			# this split preserves existing whitespace
			split_content = re.split(r'(\s+)', mycontent)
			modified = False
			for i, token in enumerate(split_content):
				if orig_cp not in token:
					continue
				try:
					atom = Atom(token, eapi=eapi)
				except InvalidAtom:
					continue
				if atom.cp != orig_cp:
					continue
				if atom.slot is None or atom.slot != origslot:
					continue

				slot_part = newslot
				if atom.sub_slot is not None:
					if atom.sub_slot == origslot:
						sub_slot = newslot
					else:
						sub_slot = atom.sub_slot
					slot_part += "/" + sub_slot
				if atom.slot_operator is not None:
					slot_part += atom.slot_operator

				split_content[i] = atom.with_slot(slot_part)
				modified = True

			if modified:
				mycontent = "".join(split_content)

	return mycontent

def update_dbentries(update_iter, mydata, eapi=None, parent=None):
	"""Performs update commands and returns a
	dict containing only the updated items."""
	updated_items = {}
	for k, mycontent in mydata.items():
		k_unicode = _unicode_decode(k,
			encoding=_encodings['repo.content'], errors='replace')
		if k_unicode not in ignored_dbentries:
			orig_content = mycontent
			mycontent = _unicode_decode(mycontent,
				encoding=_encodings['repo.content'], errors='replace')
			is_encoded = mycontent is not orig_content
			orig_content = mycontent
			for update_cmd in update_iter:
				mycontent = update_dbentry(update_cmd, mycontent,
					eapi=eapi, parent=parent)
			if mycontent != orig_content:
				if is_encoded:
					mycontent = _unicode_encode(mycontent,
						encoding=_encodings['repo.content'],
						errors='backslashreplace')
				updated_items[k] = mycontent
	return updated_items

def fixdbentries(update_iter, dbdir, eapi=None, parent=None):
	"""Performs update commands which result in search and replace operations
	for each of the files in dbdir (excluding CONTENTS and environment.bz2).
	Returns True when actual modifications are necessary and False otherwise."""

	warnings.warn("portage.update.fixdbentries() is deprecated",
		DeprecationWarning, stacklevel=2)

	mydata = {}
	for myfile in [f for f in os.listdir(dbdir) if f not in ignored_dbentries]:
		file_path = os.path.join(dbdir, myfile)
		with io.open(_unicode_encode(file_path,
			encoding=_encodings['fs'], errors='strict'),
			mode='r', encoding=_encodings['repo.content'],
			errors='replace') as f:
			mydata[myfile] = f.read()
	updated_items = update_dbentries(update_iter, mydata,
		eapi=eapi, parent=parent)
	for myfile, mycontent in updated_items.items():
		file_path = os.path.join(dbdir, myfile)
		write_atomic(file_path, mycontent, encoding=_encodings['repo.content'])
	return len(updated_items) > 0

def grab_updates(updpath, prev_mtimes=None):
	"""Returns all the updates from the given directory as a sorted list of
	tuples, each containing (file_path, statobj, content).  If prev_mtimes is
	given then updates are only returned if one or more files have different
	mtimes. When a change is detected for a given file, updates will be
	returned for that file and any files that come after it in the entire
	sequence. This ensures that all relevant updates are returned for cases
	in which the destination package of an earlier move corresponds to
	the source package of a move that comes somewhere later in the entire
	sequence of files.
	"""
	try:
		mylist = os.listdir(updpath)
	except OSError as oe:
		if oe.errno == errno.ENOENT:
			raise DirectoryNotFound(updpath)
		raise
	if prev_mtimes is None:
		prev_mtimes = {}
	# validate the file name (filter out CVS directory, etc...)
	mylist = [myfile for myfile in mylist if len(myfile) == 7 and myfile[1:3] == "Q-"]
	if len(mylist) == 0:
		return []
	
	# update names are mangled to make them sort properly
	mylist = [myfile[3:]+"-"+myfile[:2] for myfile in mylist]
	mylist.sort()
	mylist = [myfile[5:]+"-"+myfile[:4] for myfile in mylist]

	update_data = []
	for myfile in mylist:
		file_path = os.path.join(updpath, myfile)
		mystat = os.stat(file_path)
		if update_data or \
			file_path not in prev_mtimes or \
			long(prev_mtimes[file_path]) != mystat[stat.ST_MTIME]:
			f = io.open(_unicode_encode(file_path,
				encoding=_encodings['fs'], errors='strict'),
				mode='r', encoding=_encodings['repo.content'], errors='replace')
			content = f.read()
			f.close()
			update_data.append((file_path, mystat, content))
	return update_data

def parse_updates(mycontent):
	"""Valid updates are returned as a list of split update commands."""
	eapi_attrs = _get_eapi_attrs(None)
	slot_re = _get_slot_re(eapi_attrs)
	myupd = []
	errors = []
	mylines = mycontent.splitlines()
	for myline in mylines:
		mysplit = myline.split()
		if len(mysplit) == 0:
			continue
		if mysplit[0] not in ("move", "slotmove"):
			errors.append(_("ERROR: Update type not recognized '%s'") % myline)
			continue
		if mysplit[0] == "move":
			if len(mysplit) != 3:
				errors.append(_("ERROR: Update command invalid '%s'") % myline)
				continue
			valid = True
			for i in (1, 2):
				try:
					atom = Atom(mysplit[i])
				except InvalidAtom:
					atom = None
				else:
					if atom.blocker or atom != atom.cp:
						atom = None
				if atom is not None:
					mysplit[i] = atom
				else:
					errors.append(
						_("ERROR: Malformed update entry '%s'") % myline)
					valid = False
					break
			if not valid:
				continue

		if mysplit[0] == "slotmove":
			if len(mysplit)!=4:
				errors.append(_("ERROR: Update command invalid '%s'") % myline)
				continue
			pkg, origslot, newslot = mysplit[1], mysplit[2], mysplit[3]
			try:
				atom = Atom(pkg)
			except InvalidAtom:
				atom = None
			else:
				if atom.blocker:
					atom = None
			if atom is not None:
				mysplit[1] = atom
			else:
				errors.append(_("ERROR: Malformed update entry '%s'") % myline)
				continue

			invalid_slot = False
			for slot in (origslot, newslot):
				m = slot_re.match(slot)
				if m is None:
					invalid_slot = True
					break
				if "/" in slot:
					# EAPI 4-slot-abi style SLOT is currently not supported.
					invalid_slot = True
					break

			if invalid_slot:
				errors.append(_("ERROR: Malformed update entry '%s'") % myline)
				continue

		# The list of valid updates is filtered by continue statements above.
		myupd.append(mysplit)
	return myupd, errors

def update_config_files(config_root, protect, protect_mask, update_iter, match_callback = None):
	"""Perform global updates on /etc/portage/package.*, /etc/portage/profile/package.*,
	/etc/portage/profile/packages and /etc/portage/sets.
	config_root - location of files to update
	protect - list of paths from CONFIG_PROTECT
	protect_mask - list of paths from CONFIG_PROTECT_MASK
	update_iter - list of update commands as returned from parse_updates(),
		or dict of {repo_name: list}
	match_callback - a callback which will be called with three arguments:
		match_callback(repo_name, old_atom, new_atom)
	and should return boolean value determining whether to perform the update"""

	repo_dict = None
	if isinstance(update_iter, dict):
		repo_dict = update_iter
	if match_callback is None:
		def match_callback(repo_name, atoma, atomb):
			return True
	config_root = normalize_path(config_root)
	update_files = {}
	file_contents = {}
	myxfiles = [
		"package.accept_keywords", "package.env",
		"package.keywords", "package.license",
		"package.mask", "package.properties",
		"package.unmask", "package.use", "sets"
	]
	myxfiles += [os.path.join("profile", x) for x in (
		"packages", "package.accept_keywords",
		"package.keywords", "package.mask",
		"package.unmask", "package.use",
		"package.use.force", "package.use.mask",
		"package.use.stable.force", "package.use.stable.mask"
	)]
	abs_user_config = os.path.join(config_root, USER_CONFIG_PATH)
	recursivefiles = []
	for x in myxfiles:
		config_file = os.path.join(abs_user_config, x)
		if os.path.isdir(config_file):
			for parent, dirs, files in os.walk(config_file):
				try:
					parent = _unicode_decode(parent,
						encoding=_encodings['fs'], errors='strict')
				except UnicodeDecodeError:
					continue
				for y_enc in list(dirs):
					try:
						y = _unicode_decode(y_enc,
							encoding=_encodings['fs'], errors='strict')
					except UnicodeDecodeError:
						dirs.remove(y_enc)
						continue
					if y.startswith(".") or y in VCS_DIRS:
						dirs.remove(y_enc)
				for y in files:
					try:
						y = _unicode_decode(y,
							encoding=_encodings['fs'], errors='strict')
					except UnicodeDecodeError:
						continue
					if y.startswith("."):
						continue
					recursivefiles.append(
						os.path.join(parent, y)[len(abs_user_config) + 1:])
		else:
			recursivefiles.append(x)
	myxfiles = recursivefiles
	for x in myxfiles:
		f = None
		try:
			f = io.open(
				_unicode_encode(os.path.join(abs_user_config, x),
				encoding=_encodings['fs'], errors='strict'),
				mode='r', encoding=_encodings['content'],
				errors='replace')
			file_contents[x] = f.readlines()
		except IOError:
			continue
		finally:
			if f is not None:
				f.close()

	ignore_line_re = re.compile(r'^#|^\s*$')
	if repo_dict is None:
		update_items = [(None, update_iter)]
	else:
		update_items = [x for x in repo_dict.items() if x[0] != 'DEFAULT']
	for repo_name, update_iter in update_items:
		for update_cmd in update_iter:
			for x, contents in file_contents.items():
				skip_next = False
				for pos, line in enumerate(contents):
					if skip_next:
						skip_next = False
						continue
					if ignore_line_re.match(line):
						continue
					atom = line.split()[0]
					if atom[:1] == "-":
						# package.mask supports incrementals
						atom = atom[1:]
					if atom[:1] == "*":
						# packages file supports "*"-prefixed atoms as indication of system packages.
						atom = atom[1:]
					if not isvalidatom(atom):
						continue
					new_atom = update_dbentry(update_cmd, atom)
					if atom != new_atom:
						if match_callback(repo_name, atom, new_atom):
							# add a comment with the update command, so
							# the user can clearly see what happened
							contents[pos] = "# %s\n" % \
								" ".join("%s" % (x,) for x in update_cmd)
							contents.insert(pos + 1,
								line.replace("%s" % (atom,),
								"%s" % (new_atom,), 1))
							# we've inserted an additional line, so we need to
							# skip it when it's reached in the next iteration
							skip_next = True
							update_files[x] = 1
							sys.stdout.write("p")
							sys.stdout.flush()

	protect_obj = ConfigProtect(
		config_root, protect, protect_mask)
	for x in update_files:
		updating_file = os.path.join(abs_user_config, x)
		if protect_obj.isprotected(updating_file):
			updating_file = new_protect_filename(updating_file)
		try:
			write_atomic(updating_file, "".join(file_contents[x]))
		except PortageException as e:
			writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
			writemsg(_("!!! An error occurred while updating a config file:") + \
				" '%s'\n" % updating_file, noiselevel=-1)
			continue

def dep_transform(mydep, oldkey, newkey):
	if dep_getkey(mydep) == oldkey:
		return mydep.replace(oldkey, newkey, 1)
	return mydep
