#!/usr/bin/env python
import query
import parser
import index
import re
import os
import sys
import traceback
from time import clock
from datetime import timedelta
from itertools import imap
import unittest

#in case of fire
maxTrace = 10

def _readIn(x):
    return re.split(":", x)

def _writeOut(x):
    return x[0] + ":" + str(x[1])

def run(model, lib, queries, rDir, t=10, ape="min", apd="mean", u=None, k=0.4, m="none"):
    
    def defuse(st):
        return re.sub("[\/\\\[\]\(\)\{\}]+", "", re.sub("[ .:+\-*,~#%&?<>|@'!]+", "_", st))
    
    def moS(model):
        return defuse(re.split(os.path.sep, model)[-1])
    
    def uS(u):
        if u is None:
            return "tick"
        return defuse("shift {:.3}".format(u))
    
    def aS(a, s):
        while not a.lower() in query.Agg.astrats:
            a = raw_input("invalid a {}, choose: 'max', 'min', 'mean' or 'quadratic mean': ".format(s)).lower()
        return a
    
    def muS(m):
        while not m.lower() in parser.Mult.mstrats:
            m = raw_input("invalid m, choose: 'none', 'tf' or 'itf': ").lower()
        return m
    
    def runQuery(q, x, t, ape, apd, u):
        print "running query:", x[0]
        return [x[0], q.query(x[1], t, ape, apd, u)]
    
    ape = aS(ape, "per entry")
    apd = aS(apd, "per document")
    m = muS(m)
    fname = "m_{}__l_{}__q_{}__t_{}__ape_{}__apd_{}__u_{}__k_{}__m_{}.txt".format(moS(model), defuse(lib), moS(queries), t, ape, apd, uS(u), k, m)
    print "\n\nNOW TESTING\n\n", fname, "\n\n", "-" * int(os.popen('stty size', 'r').read().split()[1])
    t0 = clock()
    success = False
    try:
        q = query.Instance(model)
        q.index.addLib(lib, k, m)
        with open(queries) as f:
            qlist =  imap(_readIn, f.readlines())
        with open(os.getcwd() + os.path.sep + rDir + fname, 'w') as f:
            f.write("\n".join(x for x in imap(_writeOut, imap(lambda x: runQuery(q, x, t, ape, apd, u), qlist))))
        success = True
    except:
        traceback.print_exc(maxTrace)
    t1 = clock()
    print "test {} in {}: ".format("completed" if success  else "aborted", timedelta(seconds=t1-t0)) + fname + "\n"
    
if __name__ == '__main__':
    def suite():
        suites = []
        suites.append(unittest.TestLoader().loadTestsFromTestCase(parser._TestMult))
        suites.append(unittest.TestLoader().loadTestsFromTestCase(parser._TestInstance))
        suites.append(unittest.TestLoader().loadTestsFromTestCase(index._TestInstance))
        suites.append(unittest.TestLoader().loadTestsFromTestCase(query._TestAgg))
        suites.append(unittest.TestLoader().loadTestsFromTestCase(query._TestInstance))
        suite = unittest.TestSuite(suites)
        return suite
    v = int(raw_input("verbosity [0=silent, 1=dots, 2=verbose]: "))
    print "\n","-"*70, "\n", "test start"
    unittest.TextTestRunner(verbosity=v).run(suite())