#!/usr/bin/env python3
import re, argparse
from os import path


prog_name = "Zittrigsubersetzer (ZUS)"
prog_version = "0.1.0"


class Rule:
	def __init__(self, pre, post, lc):
		self.pre = pre
		self.post = post
		self.lc = lc

	def sub(self, text):
		try:
			return re.sub(self.pre, self.post, text, \
			              flags=re.IGNORECASE)
		except:
			print(f"error: messed up rule on line {self.lc}")
			print(f"\t pre: {self.pre}\n\tpost: {self.post}")
			raise


class RuleSet:
	def __init__(self):
		self.rules = list()

	def add_rule(self, pre, post, lc):
		self.rules.append(Rule(pre, post, lc))

	def load(self, fd):
		for i, line in enumerate(fd):
			line = re.sub("#.*$", "", line) # strip comments
			line = line.strip() # strip whitespace

			if not line:
				continue

			try:
				(pre, post) = line.split("//")
				pre = pre.strip()
				post = post.strip()
			except ValueError:
				print(f"error: shit on line {i + 1}")
				raise # raise raise zittrigmann

			self.add_rule(pre, post, i + 1)
		return ruleset

	def translate(self, text):
		text = text.upper()
		for rule in self.rules:
			text = rule.sub(text)
		return text

	def translate_debug(self, text):
		text = text.upper()
		print(text)
		for i, rule in enumerate(self.rules):
			before = text
			after = rule.sub(before)
			if before == after:
				continue
			else:
				print(f"(rule {i:2d}: s/{rule.pre}/{rule.post}/)")
				print(after)
			text = after
		return text


def mode_normal(args, ruleset):
	while True:
		try:
			text = input()
			if args.debug:
				print(ruleset.translate_debug(text))
			else:
				print(ruleset.translate(text))
		except (EOFError, KeyboardInterrupt):
			exit(0)


def mode_test(args, ruleset):
	longest_input = 3
	table = list()

	with open(args.tests, "r", encoding="UTF-8") as fd:
		for test in fd:
			test = re.sub("#.*$", "", test)
			test = test.strip()
			if not test:
				continue

			if len(test) > longest_input:
				longest_input = len(test)
				
			output = ruleset.translate(test)
			table.append((test, output))

	for (input, output) in table:
		input = input.ljust(longest_input, " ")
		print(f"{input} {output}")


if __name__ == '__main__':
	parser = argparse.ArgumentParser()
	parser.add_argument("-v", "--version", action="store_true",
	                    help="print version")
	parser.add_argument("-D", "--debug", action="store_true", \
	                    help="be more verbose (for debugging)")
	parser.add_argument("-R", "--ruleset", \
	                    help="path to file with the rules")
	parser.add_argument("-T", "--tests", help="path to the tests file")
	args = parser.parse_args()

	if args.version:
		print(f"{prog_name} {prog_version}")
		exit(0)

	if not args.ruleset:
		dirname = path.dirname(path.realpath(__file__))
		args.ruleset = path.join(dirname, "rules.txt")

	ruleset = RuleSet()
	with open(args.ruleset, "r", encoding="UTF-8") as fd:
		ruleset.load(fd)

	if args.tests:
		mode_test(args, ruleset)
	else:
		mode_normal(args, ruleset)