#!/usr/bin/python

import errno
import optparse
import os
import re
import socket
import sys
import time

sys.path[:0] = [(os.path.join(os.path.dirname(sys.argv[0]), "../.."))]

import chakana.threads
import chakana.event
import chakana.harness
import chakana.utils

from chakana.debug import *

def main(argv):
  sys.stdout = chakana.utils.UnbufferedFile(sys.stdout)
  make_option = optparse.make_option
  parser = optparse.OptionParser(
    usage = os.path.basename(argv[0]) +
    """ [options]""",
    option_list = [
    make_option("-c", "--cooja-timeout", action = "store", type = "int",
                default = 300,
                help = "Timeout waiting for COOJA to start"),
    make_option("-q", "--quiet", action = "count", default = 0,
                help = "Decrease verbosity"),
    make_option("-t", "--timeout", action = "store", type = "int",
                default = 3600,
                help = "Timeout before aborting the whole test"),
    make_option("-v", "--verbose", action = "count", default = 0,
                help = "Increase verbosity"),
    make_option("-s", "--showCOOJA", action = "store", type = "str",
                default = "False",
                help = "Show COOJA GUI"),
    make_option("-x", "--compileCOOJA", action = "store", type = "str",
                default = "True",
                help = "Compile COOJA before test"),
    ])
  (options, args) = parser.parse_args(argv)
  debugStream.increaseLevel(options.verbose - options.quiet)
  debugStream.cleanLog()
  debugStream.pushTransformer(threadPrefix)

  testDir = os.path.dirname(argv[0])
  chakanaRoot = os.path.join(testDir, "..")
  harness = chakana.harness.Harness(chakanaRoot, options.cooja_timeout, doCompile=options.compileCOOJA, withGUI=options.showCOOJA)


  ## TEST START ##
  # Start test examples:
  # > ./run_test.py
  # > ./run_test.py -v 1
  # > ./run_test.py -v 1 --compileCOOJA=False --showCOOJA=True
  
  
  
  # Test configuration (read from file?)
  totalSimulationRuns = 5
  randomSeed = 12345 # Initial random seed
  logFilename = "test.log"
  logFile = open(logFilename, 'w')
  debug(MajorEvent, "Configuration read")

  # Create log file
  title = 'TEST STARTED AT: ' + time.asctime(time.localtime(time.time()))
  logFile.write(title + '\n')
  logFile.write(''.zfill(len(title)).replace("0", "-") + '\n\n') 
  logFile.write('Log file: ' + logFilename + '\n') 
  logFile.write('Simulation runs: ' + str(totalSimulationRuns) + '\n') 
  logFile.write('Initial random seed: ' + str(randomSeed) + '\n') 
  logFile.write('\n') 
  logFile.close()
  debug(MajorEvent, "Log file created")
  
  try:
    try:
      nrSimulationRuns = 0
      while nrSimulationRuns < totalSimulationRuns:

        ## TEST RUN START ##

        # If not the first test run, shut down COOJA
        if nrSimulationRuns > 0:
          harness.quit()
          harness.waitForAllThreads(options.timeout)
          randomSeed = randomSeed + 1
          debug(MajorEvent, "Simulation removed and COOJA shut down")

        # Log current test run
        nrSimulationRuns = nrSimulationRuns + 1
        logFile = open(logFilename, 'a')                    
        logFile.write('\nTest run: ' + str(nrSimulationRuns) + '\n')
        logFile.write('Random seed: ' + str(randomSeed) + '\n') 
        logFile.close() 

        # Start COOJA
        # This may include compiling COOJA
        harness.start()
        shepherd = harness.shepherd()

        # Create new simulation from stripped COOJA simulation config
        # The XML contents are generated by creating a simulation in COOJA, 
        # saving it to file (.csc), and finally extracting the simulation specifics.
        xmlContent = chakana.utils.readFile(os.path.join(testDir, "simple_simulation.csc"))
        xmlContent = xmlContent.replace("[RANDOMSEED]", str(randomSeed))
        shepherd.loadConfigurationXML(xmlContent)
        debug(MajorEvent, "COOJA started, and simulation created")

        # Create and wait for a simple time monitor (100 sec)
        def waitTime(monitor, delay=1000):
          startTime = shepherd.getSimulationInfo(type = "time")
          debug(MajorEvent, "Waiting " + str(delay) + " ms, starting at " + str(startTime))
          monitor.waitFor(chakana.event.TimeEventpoint(shepherd, startTime + delay))
          debug(MajorEvent, "Waiting finished at " + str(startTime + delay))

        waitMon = shepherd.newMonitor(waitTime, 100000)
        waitMon.startMonitor()
        waitMon.waitMonitor()

        logFile = open(logFilename, 'a')
        logFile.write('Test run ended\n')
        logFile.close()

        ## TEST RUN END ##

    except:
      debug(Debug, "Exception detected:\n" + exceptionDump(sys.exc_info()))
      harness.killAllProcesses()
      raise

  finally:
    harness.quit()
    harness.waitForAllThreads(options.timeout)
    debug(MajorEvent, "Simulation removed and COOJA shut down")
    harness.waitForAllThreads(options.timeout)

if __name__ == "__main__":
  sys.exit(main(sys.argv))
