# -*- coding:utf-8 -*-


import difflib
import io
import re
from tempfile import mkstemp

from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
from portage import os
from portage import shutil
from portage import util


_copyright_re1 = \
	re.compile(br'^(# Copyright \d\d\d\d)-\d\d\d\d( Gentoo Foundation)\b')
_copyright_re2 = \
	re.compile(br'^(# Copyright )(\d\d\d\d)( Gentoo Foundation)\b')


class _copyright_repl(object):
	__slots__ = ('year',)

	def __init__(self, year):
		self.year = year

	def __call__(self, matchobj):
		if matchobj.group(2) == self.year:
			return matchobj.group(0)
		else:
			return matchobj.group(1) + matchobj.group(2) + \
				b'-' + self.year + matchobj.group(3)


def update_copyright_year(year, line):
	"""
	These two regexes are taken from echangelog
	update_copyright(), except that we don't hardcode
	1999 here (in order to be more generic).
	"""
	is_bytes = isinstance(line, bytes)
	if is_bytes:
		if not line.startswith(b'# Copyright '):
			return line
	else:
		if not line.startswith('# Copyright '):
			return line

	year = _unicode_encode(year)
	line = _unicode_encode(line)

	line = _copyright_re1.sub(br'\1-' + year + br'\2', line)
	line = _copyright_re2.sub(_copyright_repl(year), line)
	if not is_bytes:
		line = _unicode_decode(line)
	return line


def update_copyright(fn_path, year, pretend=False):
	"""
	Check file for a Copyright statement, and update its year.  The
	patterns used for replacing copyrights are taken from echangelog.
	Only the first lines of each file that start with a hash ('#') are
	considered, until a line is found that doesn't start with a hash.
	Files are read and written in binary mode, so that this function
	will work correctly with files encoded in any character set, as
	long as the copyright statements consist of plain ASCII.
	"""

	try:
		fn_hdl = io.open(_unicode_encode(
			fn_path, encoding=_encodings['fs'], errors='strict'),
			mode='rb')
	except EnvironmentError:
		return

	orig_header = []
	new_header = []

	for line in fn_hdl:
		line_strip = line.strip()
		orig_header.append(line)
		if not line_strip or line_strip[:1] != b'#':
			new_header.append(line)
			break

		line = update_copyright_year(year, line)
		new_header.append(line)

	difflines = 0
	for diffline in difflib.unified_diff(
		[_unicode_decode(diffline) for diffline in orig_header],
		[_unicode_decode(diffline) for diffline in new_header],
		fromfile=fn_path, tofile=fn_path, n=0):
		util.writemsg_stdout(diffline, noiselevel=-1)
		difflines += 1
	util.writemsg_stdout("\n", noiselevel=-1)

	# unified diff has three lines to start with
	if difflines > 3 and not pretend:
		# write new file with changed header
		f, fnnew_path = mkstemp()
		f = io.open(f, mode='wb')
		for line in new_header:
			f.write(line)
		for line in fn_hdl:
			f.write(line)
		f.close()
		try:
			fn_stat = os.stat(fn_path)
		except OSError:
			fn_stat = None

		shutil.move(fnnew_path, fn_path)

		if fn_stat is None:
			util.apply_permissions(fn_path, mode=0o644)
		else:
			util.apply_stat_permissions(fn_path, fn_stat)
	fn_hdl.close()
