#!/usr/bin/env python
import subprocess
import re
import sys
import csv
from clint.textui import colored
from time import sleep

PHPCS_STANDARD="Tuna"

def parse_ranges(ranges):
	parsed_ranges = []
	for range_item in ranges:
		parsed_ranges.append(parse_range(range_item[1]))
	return parsed_ranges


def parse_range(range_item):
	split_result = range_item.split(",")
	begin = split_result[0]
	try:
		length = split_result[1]
	except IndexError:
		length = 1
	
	return (int(begin), int(begin)+int(length))

def in_range(range, val):
	return int(range[0]) <= int(val) <= int(range[1])

changed_files_command = "git diff --cached --name-only --diff-filter=AM HEAD -- *.php"
process = subprocess.Popen(changed_files_command.split(), stdout=subprocess.PIPE)

(stdout, _) = process.communicate()

errors_re = re.compile("(\d+) ERROR")
warnings_re = re.compile("(\d+) WARNING")
diff_re = re.compile("@ -(\d+(?:\,\d+)?) \+(\d+(?:\,\d+)?) @")
error_re = re.compile("(\d+) \| ERROR\s+\|([^(]*)")
found_errors = 0

critical_errors=[]

if stdout:
	for path in stdout.decode().strip().split("\n"):
		check_style_command = "phpcs --standard={} -".format(PHPCS_STANDARD).split()

		diff_command = "git diff --cached -U0 --".split()
		diff_command.append(path.strip())

		committed_file_command = "git show".split()
		committed_file_command.append(":" + path.strip())

		committed_file = subprocess.Popen(committed_file_command, stdout=subprocess.PIPE)

		phpcs = subprocess.Popen(check_style_command, stdin=committed_file.stdout, stdout=subprocess.PIPE)

		(result, _) = phpcs.communicate()
		output = result.decode()
		ansi_escape = re.compile(r'\x1b[^m]*m')
		output = ansi_escape.sub('', output)
		if "FOUND" in output:
			diff = subprocess.Popen(diff_command, stdout=subprocess.PIPE)
			(result, _) = diff.communicate()
			diff_output = result.decode()

			ranges = parse_ranges(diff_re.findall(diff_output))

			errors = error_re.findall(output)
			warnings = warnings_re.search(output)

			output = re.sub("WARNING ", str(colored.yellow("WARNING ")), output)
			output = re.sub("ERROR ", str(colored.red("ERROR ")), output)

			output = re.sub("STDIN", path, output)
			print(output)

			if len(errors) > 0:
				found_errors = 2
				for error in errors:
					for range_item in ranges:
						if in_range(range_item, error[0]):
							error = list (error)
							error[1] = error[1].replace('|',"")
							error[1] = re.compile("\s+").sub(' ',error[1])
							critical_errors.append((error, path))
							found_errors = 3
			elif int(warnings.group(1)) > 0:
				if found_errors < 1:
					found_errors = 1


if found_errors == 3:
	print(colored.red("Style errors, aborting commit"))
	for error, path in critical_errors:
		print("line " + error[0] + " in " + path + " => " + error[1])
	sys.exit(1)
if found_errors == 2:
	print(colored.yellow("Style errors, in unchanged code"))
	sleep(1)
elif found_errors == 1:
	print(colored.yellow("Style warnings, proceeding"))
	sleep(1)
else:
	print(colored.green("Everything okay :)"))