#!/usr/bin/env python

from __future__ import with_statement

import os
import sys
import math
import time
import random

sys.path.insert(0, '../..')

import bufsock

def my_range(up_to):
	value = 0
	while value < up_to:
		yield value
		value += 1

class Perf:
	def __init__(self, module, description, too_long):
		self.module = module
		self.description = description
		self.too_long = too_long

	def took_too_long(self):
		if self.too_long == 0:
			return False
		if self.duration() > self.too_long:
			return True
		else:
			return False

	def duration(self):
		return self.t1 - self.t0

	def __str__(self):
		return self.description

	def start(self):
		self.t0 = time.time()

	def finish(self):
		self.t1 = time.time()
		self.difference = self.t1 - self.t0

def avg(list_):
	total = sum(list_)
	return total / len(list_)

def stddev(list_, average):
	total = 0.0
	for element in list_:
		total += (element - average) ** 2
	return math.sqrt(total)

def main():

	description = ''
	import_style = ''
	max_duration_at_1024 = 0
	size = -1

	while sys.argv[1:]:
		if sys.argv[1] == '--description' and sys.argv[2:]:
			description = sys.argv[2]
			del sys.argv[1]
		elif sys.argv[1] == '--import-style' and sys.argv[2:]:
			import_style = sys.argv[2]
			del sys.argv[1]
		elif sys.argv[1] == '--max-duration' and sys.argv[2:]:
			max_duration_at_1024 = float(sys.argv[2])
			del sys.argv[1]
		else:
			sys.stderr.write('Illegal option: %s\n' % sys.argv[1])
			sys.exit(1)
		del sys.argv[1]

	file_ = open('size', 'r')
	size = int(file_.readline())
	file_.close()

	if import_style == '':
		sys.stderr.write('%s: --import-style is a required option\n' % sys.argv[0])
		sys.exit(1)
	elif import_style == 'py':
		import rolling_checksum_py_mod as rolling_checksum_mod
	elif import_style == 'psyco':
		import rolling_checksum_py_mod as rolling_checksum_mod
		import psyco
		psyco.full()
	elif import_style == 'pyx':
		import rolling_checksum_pyx_mod as rolling_checksum_mod
	else:
		sys.stderr.write('%s: Illegal value for --import-style: %s\n' % (sys.argv[0], import_style))
		sys.exit(1)

	if max_duration_at_1024 == 0:
		sys.stderr.write('%s: --max-duration is a required option\n' % sys.argv[0])
		sys.exit(1)

	# We add 10 seconds to the result of the proportion, because some python implementations take a while to start up
	adjusted_max_duration = float(max_duration_at_1024) * size / 1024 + 10
	py_mod = Perf(rolling_checksum_mod, description, adjusted_max_duration)

	# we do pyx_mod twice to avoid cache effects
	#for pm in [ pyx_mod ]:
	all_good = True
	for pm in [ py_mod ]:
		random.seed(3)

		pm.start()
		file_handle = bufsock.bufsock(bufsock.rawio('input-data', 'rb'))
		with open('%s.length' % description, 'w') as length_file:
			for _unused in pm.module.min_max_chunker(file_handle):
				length_file.write('%d\n' % len(_unused))
		file_handle.close()
		pm.finish()

		if pm.took_too_long():
			sys.stdout.write('%s: duration of %s too long: %f (needed to be below %f)\n' % (sys.argv[0], str(pm), pm.duration(), pm.too_long))
			all_good = False
		else:
			sys.stdout.write('%s: duration of %s satisfactory: %f (needed to be below %f)\n' % (sys.argv[0], str(pm), pm.duration(), pm.too_long))

	if all_good:
		sys.stdout.write('%s: All tests passed\n' % sys.argv[0])
		sys.exit(0)
	else:
		sys.stdout.write('%s: One or more tests failed\n' % sys.argv[0])
		sys.exit(1)

main()