#!/usr/bin/python
#######################################################################
#
# $Id: runYatsim.py,v 1.2 2008-02-07 05:45:42 lorenz Exp $
# 
# Copyright (C) 2004-2008 Petr Lorenz
# All rights reserved.
# 
# ##### BEGIN LICENSE BLOCK #####
#
# Version: MPL 1.1 / GPL 2.0 / LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Petr Lorenz emGine Graphical User Interface (GUI).
# 
# The Initial Developer of the Original Code is Petr Lorenz.
# Portions created by the Initial Developer are Copyright (C) 2004-2008.
# All Rights Reserved.
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the  "GPL"), or the
# GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
# case the provisions of the GPL or the LGPL are applicable instead of those
# above.  If you wish to allow use of your version of this file only under the
# terms of either the GPL or the LGPL and not to allow others to use your
# version of this file under the MPL, indicate your decision by deleting the
# provisions above and replace them with the notice and other provisions
# required by the GPL or LGPL.  If you do not delete the provisions above, a
# recipient may use your version of this file under the terms of any one of the
# MPL License, the GPL or the LGPL.
#
# ##### END LICENSE BLOCK #####
#
#######################################################################
# 
# $Log: runYatsim.py,v $
# Revision 1.2  2008-02-07 05:45:42  lorenz
# * Fixed 'Simulation Boundary View' check problem
#   when closing a project.
#
# * Fixed Bounding Box problems when moving/editing a geometry.
#
# Revision 1.1.1.1  2008-01-28 06:15:35  lorenz
# Import emGine GUI v. 0.7.1
#
# Revision 1.2  2007-07-02 06:37:24  lorenz
# Clean up of old code.
#
# Revision 1.1.1.1  2007-05-08 06:22:35  lorenz
# Initial Import
#
#######################################################################

import os, sys, getopt, thread, time
import Tkinter
import signal 

import math
#try: 
#    import awtGfx as GfxDriver
#except ImportError:
#    try:
#        import wxGfx as GfxDriver
#    except ImportError:
#        try:
#            import gtkGfx as GfxDriver
#        except ImportError:
#            import tkGfx as GfxDriver

#import tkGfx as GfxDriver
#import Graph, Gfx


GLOB_verbose = False
GLOB_version = '0.2'
GLOB_yatsimbin = 'yatsim'

# The standard file descriptors
STDIN_FILENO  = 0
STDOUT_FILENO = 1
STDERR_FILENO = 2

GLOB_t1 = 0.0
GLOB_t2 = 0.0

GLOB_RUNNING = False
GLOB_PID = 0

class runYatsim:
  def __init__(self, platform):
    self.platform = platform
    self.bin_yatsim = os.path.join("bin", platform["name"], "yatsim" + platform["execsuffix"])
    self.tmp_path = os.path.join("tmp")

  def run(self, I3Dfname_full):
    pth = os.path.split(I3Dfname_full)
    I3Dfname = pth[1]
    pth = pth[0]

    fname = I3Dfname.replace("I3D.", "")	# erase I3D prefix
    #runcmd = self.bin_yatsim + " -at -ex " + self.platform["pathquote"] + fname + self.platform["pathquote"] + " " + pth
    runcmd = self.bin_yatsim + " -at -ex " + fname + " " + pth
    print runcmd
    os.system(runcmd)

class ProgressBar:
  def __init__(self, Parent, Height=10, Width=100, 
               ForegroundColor=None,BackgroundColor=None,Progress=0):
    self.Height=Height
    self.Width=Width
    self.BarCanvas = Tkinter.Canvas(Parent,
      width=Width,height=Height,
      background=BackgroundColor,borderwidth=1,
      relief=Tkinter.SUNKEN)
    if (BackgroundColor):
      self.BarCanvas["backgroundcolor"]=BackgroundColor
    self.BarCanvas.pack(padx=5,pady=2)
    self.RectangleID=self.BarCanvas.create_rectangle(0,0,0,Height)
    if (ForegroundColor==None):
      ForegroundColor="black"
    self.BarCanvas.itemconfigure(self.RectangleID,fill=ForegroundColor)
    self.SetProgressPercent(Progress)        
  def SetProgressPercent(self,NewLevel):
    self.Progress=NewLevel
    self.Progress=min(100,self.Progress)
    self.Progress=max(0,self.Progress)        
    self.DrawProgress()
  def DrawProgress(self):
    ProgressPixel=(self.Progress/100.0)*self.Width
    self.BarCanvas.coords(self.RectangleID,
      0,0,ProgressPixel,self.Height)
  def GetProgressPercent(self):
    return self.Progress


def print_usage(progname):
  print >> sys.stderr, "Usage: %s [Options] <I3D.file>" %progname
  print >> sys.stderr, "Options:"
  print >> sys.stderr, "\t-v\tbe verbose"
  print >> sys.stderr, "\t-i\tprovide info"

def provide_info():
  #global GLOB_yatsimbin, GLOB_version

  print >> sys.stderr, "This is yatsim-run, Version %s\nyatsim info:" %GLOB_version
  os.system('%s -v' %GLOB_yatsimbin)
  #print >> sys.stderr, 

def process_progress(data, w, bar):
  global GOLB_t1, GLOB_t2

  done_v = len(data.split("*")) - 1
  #data.replace("\r", "")
  #data.replace("\n", "")
  #data.replace("\t", "")
  perc = 2.5*done_v
  #est_time = "(--:--:--)"
  est_time = ""
  w.config(text = 'Done %d %% %s' %(perc, est_time))
  if perc > 0:
    GLOB_t2 = time.time()

    bar.SetProgressPercent(perc)
    GLOB_t1 = GLOB_t2
    
  else:
    w.config(text = "Parsing the I3D file...")


def start_yatsim(fname, w, bar):
  #global GLOB_yatsimbin
  global GLOB_RUNNING
  global GLOB_PID

  ### open a window for graphics output
  ##gfx = GfxDriver.Window(title = "Simulation Time Domain Response")
  ##gr = Graph.Cartesian(gfx, -math.pi*4, -1.1, math.pi*4, 1.1, "", "t", "sin(t)")
  ##gr.addPen("sin(t)", Gfx.BLUE_PEN)
  ##for x in gr.xaxisSteps(-math.pi*4, math.pi*4):
  ##  gr.addValue("sin(t)", x, math.sin(x))
  ##gfx.refresh()
  
  # Using the pipe function (lower level than popen)
  (r_end, w_end) = os.pipe()

  # Create child process; Child pid = has zero 
  pid = os.fork()

  if pid:
    # Parent process:
    GLOB_PID = pid
    #print GLOB_PID


    # Work on file descriptors...
    os.close(w_end)
    
    #print "I am parent! Pid: ", pid
    #print "Waiting for child to finish."
    w.config(text = "Running yatsim simulation...")

    GLOB_RUNNING = True

    while 1:
      data = os.read(r_end, 1024)
      if data == '':
	break
      process_progress(data, w, bar)

    #print os.waitpid(pid, os.WNOHANG)
    (w_pid, w_retcode) = os.waitpid(pid, 0)
    #print (w_pid, w_retcode)
    GLOB_RUNNING = False

    w.config(text = "Simulation finished.")
  else:
    # Child process:
    # Close STDOUT and make a copy of w_end to STDOUT through pipe
    os.close(r_end)
    os.close(STDOUT_FILENO)
    os.dup(w_end)
    os.close(w_end)

    # Start the actual simulation
    os.execlp("%s" %GLOB_yatsimbin, "%s" %GLOB_yatsimbin, "-at", "%s" %(fname.replace('I3D.', '')))
    print >> sys.stderr, "** Panic abort! execution of simulation failed!"
    sys.exit(-1)


################################
# main
################################
if __name__ == '__main__':

  fname = ''
  
  if (len(sys.argv) < 2):
    print_usage(os.path.basename(sys.argv[0]))
    sys.exit(1)

  # Loop through all the command line arguments
  for arg in sys.argv[1:]:
    if arg[0] == '-':
      option = arg[1:]
      if option == 'v':
        GLOB_verbose = True
      elif option == 'i':
        provide_info()
        sys.exit(0)
      else:
        print '(Warning): An unknown option skipped: %s' %option
    else:
      if fname != '':
        print >> sys.stderr, "** Error! Two or more I3D files specified!"
        sys.exit(1)
      fname = arg


  # No I3D model file found?
  if fname == '':
    print >> sys.stderr, "** Error! No I3D file specified!"
    sys.exit(1)

  # Prepare the I3D model file name
  if fname.find("I3D") == -1:
    fname = "I3D." + fname

  # Create the GUI windows
  root = Tkinter.Tk()
  root.title("yatsim-run")
  wtit = Tkinter.Label(root, text = "%s" %fname)
  wtit.pack()

  w = Tkinter.Label(root, text="Hello Yatsim User :)")
  w.pack()

  bar = ProgressBar(root, 20, 200)

  # Start the simulation
  sim_thid = thread.start_new_thread(start_yatsim, (fname, w, bar))
  #print sim_thid

  root.mainloop()

  if GLOB_RUNNING == True:
    #print "Job is running!!!!"
    if GLOB_PID != 0:
      os.kill(GLOB_PID, signal.SIGKILL)
  #print "Main loop finished"
