#!/usr/bin/python
#-*- coding: utf8 -*-

import os
import subprocess
import sys
import glob
from optparse import OptionParser

TESTS = []
TESTFOLDER = 'tests'
LIBFOLDER = 'lib'

if not os.path.isdir(TESTFOLDER):
	TESTFOLDER = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'tests')
if not os.path.isdir(LIBFOLDER):
	LIBFOLDER = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib')

# Append the usi-check libs to python path
ENV = os.environ.copy()
if 'PYTHONPATH' not in ENV:
	ENV['PYTHONPATH'] = LIBFOLDER
else:
	ENV['PYTHONPATH'] += os.pathsep + LIBFOLDER


def getUSILocation(currentDir):
	if currentDir.endswith('univention-support-info'):
		BASEDIR = currentDir
	elif 'univention-support-info' in currentDir:
		return currentDir
	else:
		BASEDIR = os.path.join(currentDir, 'univention-support-info')

	if not os.path.isdir(BASEDIR):
		if os.path.isdir(os.path.join(currentDir, 'files')) and os.path.isdir(os.path.join(currentDir, 'info')):
			return currentDir
		else:
			#TODO giv better info on error
			raise IOError('Base directory not found! [%s]' % (BASEDIR))

	# get sub folders
	dirs = [name for name in os.listdir(BASEDIR) if os.path.isdir(os.path.join(BASEDIR, name))]
	if len(dirs) == 1:
		return os.path.join(BASEDIR, dirs[0])
	elif len(dirs) == 0:
		print("ERROR - dirs: %s | BASEDIR: '%s'" % (repr(dirs), BASEDIR))
	else:
		# TODO selectable subdir
		print("%s" % (repr(dirs)))

	return BASEDIR


class Test:
	def __init__(self, script=None, category=None, usi=None, executed=False, result=None, exitcode=None):
		self.script = script
		self.category = category
		self.usi = usi
		self.executed = False
		self.result = None
		self.exitcode = exitcode

	def __str__(self):
		return self.category + '/' + self.script + ': ' + repr(self.result)

	def run(self, verbose):
		self.executed = True
		filename = os.path.join(TESTFOLDER, self.category, self.script)
		args = self.usi
		process = subprocess.Popen([filename, args], env=ENV, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
		stderr = process.stderr.read()
		# FIXME: Only print stderr in verbose mode
		if stderr and verbose:
			sys.stderr.write(self.script + ':\n')
			sys.stderr.write(''.join(stderr))

		stdout = process.stdout.read()
		process.communicate()[0]
		self.exitcode = process.returncode
		self.result = stdout

	def report(self, verbose):
		if self.executed and (self.exitcode != 0 or verbose):
			print(self.script)
			for line in self.result.split('\n'):
				print("  %s" % (line.rstrip()))


def getTests(category='*'):
	'''
	fetches all available tests and initializes them
	these should be specified as bash/python scripts underneath folder tests/category
	'''
	for cat in sorted(category.split(',')):
		for fpath in sorted(glob.glob(os.path.join(TESTFOLDER, cat, '*'))):
			t = Test(script=os.path.basename(fpath),
						category=os.path.basename(os.path.dirname(fpath)),
						usi=options.usifolder)
			yield t


if __name__ == '__main__':
	parser = OptionParser()
	parser.add_option("-u", "--usi", dest="usifolder",
						help="specify usi-folder", metavar="USI")
	parser.add_option("-c", "--category", dest="category",
						help="specify category", metavar="CATEGORY",
						default='*')
	parser.add_option("-f", "--folder", dest="gofolder", default=False,
				help="go to usi folder", metavar="FOLDER")
	parser.add_option("-n", "--noskip", action="store_false", dest="skip_empty",
				default=True, help="dont't skip successful test", metavar="SKIPTEST")
	parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
				default=False, help="be verbose", metavar="DEBUG")

	(options, args) = parser.parse_args()
	if args and not options.usifolder:
		options.usifolder = args[0]
	elif not args and not options.usifolder:
		options.usifolder = getUSILocation(os.getcwd())
	options.usifolder = os.path.join(os.path.realpath(options.usifolder))

	print("Support-Info-Archiv report for '%s'\n" % (options.usifolder))
	last_cat = ''
	for test in getTests(options.category):
		if options.verbose:
			print("running test '%s'..." % (test.script))
		test.run(options.verbose)
		if test.exitcode > 0 or not options.skip_empty:
			if last_cat != test.category:
				print("\033[36;1mCategory: %s\033[0m" % (test.category))
				last_cat = test.category
			test.report(options.verbose)

	if options.gofolder:
		os.chdir(options.usifolder)
