#! /usr/bin/python
#
#  File: helena-test
#

import os
import subprocess
import random
import shutil
import sys

class Model:
    def launchHelena(self, l):
        (model, _) = os.path.splitext(self.modelFile)
        d = self.outDir + os.sep
        md = d + "test-" + str(self.testNum)
        args = "helena " + " ".join(l) + " --model-directory=" + md + " "\
            "--report-file=report.xml " + \
            "-sl=1000000 -tl=60 " + self.modelFile
        print args
        errFile = open(d + "test-" + str(self.testNum) + ".err", "w")
        subprocess.call(args, stderr = errFile,
                        stdout = self.outFile, shell = True)
        errFile.close()
        if os.path.exists("report.xml"):
            n = d + "test-" + str(self.testNum) + ".xml"
            os.rename("report.xml", n)
            if self.buildRG:
                p = d + "test-" + str(self.testNum) + ".pdf"
                subprocess.call("helena-graph" +
                                " " + md + os.sep + "rg-report.xml " + p,
                                shell = True)
        else:
            f = open(d + "test-" + str(self.testNum) + ".xml", "w")
            f.write("error")
            f.close()
        f = open(d + "test-" + str(self.testNum) + ".opt", "w")
        f.write(" ".join(l))
        f.close()
        shutil.rmtree(md)
        self.testNum = self.testNum + 1
    def appendStateCaching(self, l):
        f = self.next [ self.appendStateCaching ]
        f(l + ["-S=0"])
        if self.compress:
            f(l + ["-S=1", "-s=1000"])
    def appendDelta(self, l):
        f = self.next [ self.appendDelta ]
        f(l + ["-D=0"])
        if self.compress:
            f(l + ["-D=1"])
    def appendHashCompaction(self, l):
        f = self.next [ self.appendHashCompaction ]
        f(l + ["-H=0"])
        if "-A=dfs" in l and self.compress:
            self.compress = False
            f(l + ["-H=1"])
            self.compress = True
    def appendPartialOrder(self, l):
        f = self.next [ self.appendPartialOrder ]
        f(l + ["-P=0"])
        if self.por:
            f(l + ["-P=1"])
    def appendAlgo(self, l):
        f = self.next [ self.appendAlgo ]
        if not self.buildRG:
            f(l + ["-A=dfs"])
            if not self.ltl:
                f(l + ["-A=bfs"])
                self.compress = False
                self.por = False
                f(l + ["-A=rwalk"])
                self.compress = True
                self.por = True
        elif not self.ltl:
            self.compress = False
            self.por = False
            f(l + ["-A=delta-ddd"])
            self.compress = True
            self.por = True
    def appendAction(self, l):
        f = self.next [ self.appendAction ]
        (model, _) = os.path.splitext(self.modelFile)
        self.buildRG = True
        self.compress = False
        self.por = False
        f(l + ["-N=build-graph"])
        self.compress = True
        self.por = True
        self.buildRG = False
        f(l + ["-N=explore"])
        propFile = model + ".prop.lna"
        if os.path.exists(propFile):
            pf = open(propFile)
            for str in pf:
                fields = str.split()
                if len(fields) >= 3 and fields[1] == "property":
                    prop = fields[2].split(":")[0]
                    self.ltl = fields[0] == "ltl"
                    f(l + [ "-N=check-" + prop ])
                    self.ltl = False
            pf.close()
    def launchTest(self):
        print "=====  " + self.modelFile + " ====="
        self.outFile = open(os.devnull, "w")
        self.appendAction([])
    def __init__(self, modelFile, outDir):
        self.outFile = None
        self.check = False
        self.ltl = False
        self.por = True
        self.compress = True
        self.buildRG = False
        self.modelFile = modelFile
        self.outDir = outDir + os.sep + os.path.basename(self.modelFile)
        self.next = { self.appendAction          : self.appendAlgo,
                      self.appendAlgo            : self.appendPartialOrder,
                      self.appendPartialOrder    : self.appendHashCompaction,
                      self.appendHashCompaction  : self.appendDelta,
                      self.appendDelta           : self.appendStateCaching,
                      self.appendStateCaching    : self.launchHelena }
        self.testNum = 0
        os.mkdir(self.outDir)

inDir  = sys.argv[1]
outDir = sys.argv[2]
os.mkdir(outDir)
for(_, _, files) in os.walk(inDir):
    for f in files:
        (f, ext) = os.path.splitext(f)
        if ext == ".lna":
            (_, ext2) = os.path.splitext(f)
            if ext2 != ".prop":
                m = Model(os.path.abspath(inDir + os.sep + f + ext), outDir)
                m.launchTest()
    break
