"""
     qtgui/main.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2011 University of York
     Copyright (C) 2012 STFC

     This library is free software: you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public License
     version 3, modified in accordance with the provisions of the 
     license to address the requirements of UK law.
 
     You should have received a copy of the modified GNU Lesser General 
     Public License along with this library.  If not, copies may be 
     downloaded from http://www.ccp4.ac.uk/ccp4license.php
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
"""
import sys,os,glob
import re
import time
import traceback

try:
  # This only matters for site-packes installed version.
  # It is a stub which sets sys.path appropriately.
  import ccp4mg
except:
  pass

if sys.argv.count('-osmesa'):
  import mgOSMesa as opengl
else:
  import opengl
from PyQt4 import QtGui,QtCore,QtOpenGL
import cprim

if __name__ == "__main__" and sys.platform == "linux2":
  """
  On 64 bit debian 5, File->Open somehow attempts to load
  /usr/lib/libxml2.so.2 which then resolves symbols incorrectly
  against ccp4mg/lib/libz.so.1. What *should* happen (and does
  everywhere else is that  ccp4mg/lib/libxml2.so.2 should be
  loaded. Here, we force this to happen so that it is cached for
  later attempt.
  """
  import platform
  platter = platform.platform()
  if 'debian-5' in platter and 'x86_64' in platter:
    import ctypes
    from ctypes.util import find_library
    cdum = ctypes.CDLL(find_library("xml2"))

def random_splash_file():
  file_list = glob.glob(os.path.join(os.environ["CCP4MG"],"splash",'*.png'))
  #print 'random_splash_file',file_list
  if not file_list: return os.path.join(os.environ["CCP4MG"],"splash.png")
  ii = int(time.time()%len(file_list))
  return file_list[ii]
                        
class BevelledSplashScreen(QtGui.QSplashScreen):
	def __init__(self,pixmap):
		QtGui.QSplashScreen.__init__(self,pixmap)

	def drawContents(self,painter):
		QtGui.QSplashScreen.drawContents(self,painter)
		path = QtGui.QPainterPath()
		border_width = 4
		path.moveTo(0,0)
		path.lineTo(border_width,border_width)
		path.lineTo(border_width,self.height()-(border_width))
		path.lineTo(0,self.height())
		path.lineTo(0,0)
		pen = QtGui.QPen(QtGui.QColor(0,0,0))
		painter.setPen(pen)
		#brush = QtGui.QBrush(endColour)
		startColour = QtGui.QColor(255,255,255)
		endColour = QtGui.QColor(96,96,96)
		linearGrad = QtGui.QLinearGradient(QtCore.QPointF(10, 0),QtCore.QPointF(0, 0))
		linearGrad.setColorAt(0,startColour)
		linearGrad.setColorAt(1,endColour)
		brush = QtGui.QBrush(linearGrad)
		painter.fillPath(path,brush)
		path = QtGui.QPainterPath()
		path.moveTo(self.width(),0)
		path.lineTo(self.width()-(border_width),border_width)
		path.lineTo(self.width()-(border_width),self.height()-(border_width))
		path.lineTo(self.width(),self.height())
		path.lineTo(self.width(),0)
		#brush = QtGui.QBrush(QtGui.QColor(128,128,128))
		startColour = QtGui.QColor(255,255,255)
		endColour = QtGui.QColor(96,96,96)
		linearGrad = QtGui.QLinearGradient(QtCore.QPointF(self.width()-(border_width), 0),QtCore.QPointF(self.width()-1, 0))
		linearGrad.setColorAt(0,startColour)
		linearGrad.setColorAt(1,endColour)
		brush = QtGui.QBrush(linearGrad)
		painter.fillPath(path,brush)
		path = QtGui.QPainterPath()
		path.moveTo(0,0)
		path.lineTo(border_width,border_width)
		path.lineTo(self.width()-(border_width+1),border_width)
		path.lineTo(self.width(),0)
		path.lineTo(0,0)
		#brush = QtGui.QBrush(QtGui.QColor(192,192,192))
		startColour = QtGui.QColor(255,255,255)
		endColour = QtGui.QColor(160,160,160)
		linearGrad = QtGui.QLinearGradient(QtCore.QPointF(0,border_width),QtCore.QPointF(0,0))
		linearGrad.setColorAt(0,startColour)
		linearGrad.setColorAt(1,endColour)
		brush = QtGui.QBrush(linearGrad)
		painter.fillPath(path,brush)
		path = QtGui.QPainterPath()
		path.moveTo(0,self.height())
		path.lineTo(border_width,self.height()-(border_width))
		path.lineTo(self.width()-(border_width),self.height()-(border_width))
		path.lineTo(self.width(),self.height())
		path.lineTo(0,self.height())
		#brush = QtGui.QBrush(QtGui.QColor(64,64,64))
		startColour = QtGui.QColor(255,255,255)
		endColour = QtGui.QColor(32,32,32)
		linearGrad = QtGui.QLinearGradient(QtCore.QPointF(0,self.height()-(border_width+1)),QtCore.QPointF(0,self.height()-1))
		linearGrad.setColorAt(0,startColour)
		linearGrad.setColorAt(1,endColour)
		brush = QtGui.QBrush(linearGrad)
		painter.fillPath(path,brush)

class MainLoop:
  def __del__(self):
    print "Finishing CCP4MG MainLoop"

  def __init__(self):

    pass
    """
    import resources
    self.resources = resources.CResources()
    self.resources.load_resources()
    """

  def initialize(self,app):
    from MGMainWindow import MGMainWindow, MGMainWindowSimple
    import mgapp
    import global_definitions,rebuild

    developer = 1
    # Parse the command line
    HISTORY = global_definitions.HISTORY()
    rv = HISTORY.parse_program_command_line()
    #HISTORY.recoverAutoSave()
    # rv!="" implies error parsing command line or command belongs to plugin
    # No need to go through usual exit protocols cos nothing set up
    if type(rv) == str and rv!="" and not sys.argv.count('-quit'): 
	QtGui.QMessageBox.critical(None, "Input commmand not recognised",rv, QtGui.QMessageBox.Ok )

    #translator = QtCore.QTranslator()
    # This is interesting, if a little silly in the latin case ...
    #translator.load(":/pyqtmg_la")
    #translator.load(":/pyqtmg_en")
    #app.installTranslator(translator)

    splash_file=random_splash_file()

    if not sys.argv.count('-quit'):
      pixmap = QtGui.QPixmap(splash_file)
      pix2 = QtGui.QPixmap(pixmap)
      pix2.fill(QtCore.Qt.white)
      painter = QtGui.QPainter()
      painter.begin(pix2)
      painter.drawPixmap(0,0,pixmap)
      painter.end()
      splash = BevelledSplashScreen(pix2)
      import version
      version_string = splash.tr("CCP4MG version ") + QtCore.QString(version.ccp4mg_version)
      if sys.platform != "linux2":
        splash.showMessage(splash.tr("Starting ")+version_string,QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom,QtCore.Qt.black)
      splash.show()
      splash.raise_()
      if sys.platform == "linux2":
        splash.showMessage(splash.tr("Starting ")+version_string,QtCore.Qt.AlignHCenter|QtCore.Qt.AlignBottom,QtCore.Qt.black)

    dockedDT = 1
    super_compact = 0
    try:
      params2 = HISTORY.restore_params('params2')
      if params2 and hasattr(params2,"has_key") and params2.has_key('advanced_options'):
        advOpt = params2['advanced_options']
        if advOpt and hasattr(advOpt,"has_key") and advOpt.has_key('dockable_display_table'):
          dockedDT = advOpt['dockable_display_table']
        if advOpt and hasattr(advOpt,"has_key") and advOpt.has_key('super_compact_display_table'):
          super_compact = advOpt['super_compact_display_table']
    except:
      pass

    if sys.argv.count('-quit'):
        window = MGMainWindowSimple(application=app,stereoFormatAvailable=stereoFormatAvailable)
        MGApplication._dummyWindow = window
    else:
      try:
        gui_params = HISTORY.restore_params('gui_params')
        window = MGMainWindow(application=app,gui_params=gui_params,stereoFormatAvailable=stereoFormatAvailable,dockedDT=dockedDT,super_compact=super_compact)
      except:
        window = MGMainWindow(application=app,stereoFormatAvailable=stereoFormatAvailable)

    settings = QtCore.QSettings("CCP4","CCP4MG")
    if not sys.argv.count('-quit'):
      window.restoreGeometry(settings.value("mainwindow/geometry").toByteArray())
      window.show()

    import resources
    self.resources = resources.CResources()
    self.resources.load_resources()

    if not sys.argv.count('-quit'):
      splash.finish(window)
      window.UnClose()
      splash.raise_()

    if sys.argv.count('-quit'):
      window.hide()
      if hasattr(window,"wMGDisplayTable"): window.wMGDisplayTable.hide()

    """
    import QResources
    resources = QResources.QResources()
    """

    restore_past_or_prev = False
    askRestore = True
    for arg in sys.argv:
      if re.match('-nore',arg):
         askRestore = False
         break
    if not sys.argv.count('-quit'):
      try:
        if askRestore and HISTORY.check_data_valid_last_program_status():
          restoreAnswer = QtGui.QMessageBox.question(window,"Restore status?","A saved status file exists. Would you like to restore it?",QtGui.QMessageBox.Yes| QtGui.QMessageBox.No,QtGui.QMessageBox.Yes)
          if restoreAnswer == QtGui.QMessageBox.Yes:
            restore_past_or_prev = True
      except:
        exc_type, exc_value,exc_tb = sys.exc_info()[:3]
        sys.stderr.write(str(exc_type)+'\n')
        sys.stderr.write(str(exc_value)+'\n')
        traceback.print_tb(exc_tb)
    else:
      restore_past_or_prev = True

    utils.printOutput( "Restoring program status..",developer)
    try:
      status = HISTORY.restore_program_status(restore_past_or_prev=restore_past_or_prev)
      if not sys.argv.count('-quit'):
        global_definitions.DISPLAYTABLE().loadAllDataObj()
      if status:
        utils.printOutput( "...DONE status: "+str(status))
      else:
        utils.printOutput( "...DONE")
    except:
      exc_type, exc_value,exc_tb = sys.exc_info()[:3]
      sys.stderr.write(str(exc_type)+'\n')
      sys.stderr.write(str(exc_value)+'\n')
      traceback.print_tb(exc_tb)
    if not sys.argv.count('-quit'):
      window.applyGLLighting()

    # load plugins after restoring status so plugins can be handed saved
    # status as they are initialised
    window.loadPlugins()

    # Apply the command line requests
    utils.printOutput( "Applying command line..",developer)
    try:
      status = HISTORY.apply_program_command_line()
    except:
      exc_type, exc_value,exc_tb = sys.exc_info()[:3]
      sys.stderr.write(str(exc_type)+'\n')
      sys.stderr.write(str(exc_value)+'\n')
      traceback.print_tb(exc_tb)
       
    rs = HISTORY.run_command_line_script()
    rebuild.UpdateDisplay()

    # I have no idea if this is platform independent
    #if len(sys.argv) > 1:
    #  for i in range(1,len(sys.argv)):
    #    event = QtGui.QFileOpenEvent(sys.argv[i])
    #    app.postEvent(app,event)

    if not sys.argv.count('-quit'):
      window.UnClose()
      if hasattr(window,"wMGDisplayTable"):
        try:
          window.wMGDisplayTable.UnClose()
        except:
          exc_type, exc_value,exc_tb = sys.exc_info()[:3]
          sys.stderr.write(str(exc_type)+'\n')
          sys.stderr.write(str(exc_value)+'\n')
          traceback.print_tb(exc_tb)

    window.applyStereoPrefs()

    if not sys.argv.count('-quit'):
      from global_definitions import PM,get_dispobj
      app.setProperty("flip_labels",False)
      params =  PM("miscell_prefs").getparams()
      if params.has_key('flip_text'):
        app.setProperty("flip_labels",params['flip_text'])
        for dispobj in get_dispobj(): dispobj.set_redraw_text()
        import rebuild
        rebuild.UpdateDisplay()

    if type(rv) == list:
       for plug in window.plugins:
          if hasattr(plug,"parse_program_command_line"):
             rv = plug.parse_program_command_line(rv)

    rverr = ""
    if sys.argv.count('-quit'):
      while '-quit' in rv: rv.remove('-quit')
      while '-OSMesaO' in rv:
           i = rv.index('-OSMesaO')
           if i+1<len(rv):
             if len(rv[i+1])>0 and rv[i+1][0]!='-':
               rv.pop(i)
           rv.pop(i)
      while '-osmesa' in rv:
           i = rv.index('-osmesa')
           f = 'mgosmesa.png'
           if i+1<len(rv):
             if len(rv[i+1])>0 and rv[i+1][0]!='-':
               f = rv[i+1]
               rv.pop(i)
           rv.pop(i)
           if window and hasattr(window,"glWidget") and hasattr(window.glWidget,"osMesaBuffer"):
              print "Attempting to write file",f
              try:
                window.glWidget.setDoDraw(True)
                window.glWidget.updateGL()
                window.glWidget.write(f)
                window.glWidget.setDoDraw(False)
                print "Written",f
              except:
                exc_type, exc_value = sys.exc_info()[:2]
                print "Failed to write",f, exc_type, exc_value
      utils.deleteTemporaryFiles()
      if rv or status or rs:
        print "Quitting with error"; sys.stdout.flush()
        print rv, type(rv)
        print status, type(status)
        print rs, type(rs)
        sys.exit(1)
      else:
        print "Quitting successfully"; sys.stdout.flush()
        sys.exit()
    for s in rv:
      rverr = rverr + s + " "
    if rverr!="" and not sys.argv.count('-quit'): 
	QtGui.QMessageBox.critical(None, "Input commmand not recognised","Input commmand not recognised: "+rverr, QtGui.QMessageBox.Ok )
    
    def MyExit():
      import global_definitions
      import utils
      # Cleanup and save status
      global_definitions.DISPLAYTABLE().Exit()
      global_definitions.HISTORY().Exit()
      # ??? What about cleanup/save of plugin applications
      app.closeAllWindows()
      settings = QtCore.QSettings("CCP4","CCP4MG")
      settings.setValue("mainwindow/geometry",QtCore.QVariant(window.saveGeometry()))
      if hasattr(window,"wMGDisplayTable"):
        settings.setValue("displaytable/geometry",QtCore.QVariant(window.wMGDisplayTable.saveGeometry()))
      settings.sync()
      utils.deleteTemporaryFiles()

    import atexit
    atexit.register(MyExit)

    sys.setrecursionlimit(5000)
    if not sys.argv.count('-quit') and hasattr(window,"wMGDisplayTable"):
      window.wMGDisplayTable.restoreGeometry(settings.value("displaytable/geometry").toByteArray())
      window.wMGDisplayTable.show()
      settings.sync()

class trace_print_statements_writer :
    def __init__(self, *writers) :
    	self.writers = writers

    def flush(self) :
    	for w in self.writers :
    		w.flush()

    def write(self, text) :
        traceback.print_stack()
    	for w in self.writers :
    		w.write(text)

if __name__ == "__main__":

    if os.environ.has_key("CCP4MG_DEBUG_TRACEPRINT"):
      sys.stdout = trace_print_statements_writer(sys.stdout)

    sys.argv = [ a for a in sys.argv if a != "-gdb" ]
    sys.argv = [ a for a in sys.argv if a != "-valgrind" ]
    if sys.platform == "win32":
      import mg2
      mg2.setup_pythonpath()
      import crash_handler
      import datetime
      import tempfile
      if sys.platform == "win32":
        tdir = tempfile.gettempdir()
        dumpfile = os.path.join(tdir,"CCP4MG_"+str(datetime.date.today())+'_'+time.strftime("%H-%M-%S")+".mdmp")
        crash_handler.SetCrashHandler(dumpfile)
    import MGApplication

    import utils
    # Intercept a -help command line before setting everything up
    if sys.argv.count('-help') or sys.argv.count('-h'):
      helpfile = os.path.join(os.environ["CCP4MG"],'python','etc','help.txt')
      f=utils.openFile(helpfile,'r',1)
      if f: 
        helptext=f.read()
        f.close()
        print helptext
      sys.exit()

    # Intercept a -version command line before setting everything up
    if sys.argv.count('-version'):
      from version import ccp4mg_version
      print ccp4mg_version
      sys.exit()

    tex_f = open(os.path.join(os.environ["CCP4MG"],"shaders","textures","atom_texture_coords_table"))
    tex_atoms = {}
    for l in tex_f.readlines():
      tsx, tex,tsy,tey = l[2:].split()
      cprim.TexCoords().AddCoords(l[:2],float(tsx),float(tex),float(tsy),float(tey))
    tex_f.close()

    # Do the optional redirection early in startup sequence.
    if sys.argv.count('-redirect')>0:
      while sys.argv.count('-redirect')>0:
        sys.argv.remove('-redirect')
        if sys.argv.count('-noredirect')>0:
          while sys.argv.count('-noredirect')>0:
            sys.argv.remove('-noredirect')
	else:
          utils.redirectOutput()
    if sys.argv.count('-noredirect')>0:
      while sys.argv.count('-noredirect')>0:
        sys.argv.remove('-noredirect')

    if not sys.argv.count('-quit'):
      #QtGui.QApplication.setGraphicsSystem("raster")
      app = MGApplication.MGApplication(sys.argv)
    else:
      if sys.platform != "win32":
        app = QtGui.QApplication(sys.argv,False)
      else:
        app = QtGui.QApplication(sys.argv,True)
      app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus,False)

    app.setProperty("flip_labels",False)
    if not sys.argv.count('-quit'):
      stereoFormat = QtOpenGL.QGLFormat(QtOpenGL.QGL.StereoBuffers)
      glWidgetTest = QtOpenGL.QGLWidget(stereoFormat)
      stereoFormatAvailable = glWidgetTest.format().stereo()
      glWidgetTest.close()
      glWidgetTest.deleteLater()
    else:
      stereoFormatAvailable = False

    app.addLibraryPath(os.path.join(os.environ["CCP4MG"],"QtPlugins"))
    if os.environ.has_key("CCP4"):
      app.addLibraryPath(os.path.join(os.environ["CCP4"],"QtPlugins"))
      app.addLibraryPath(os.path.join(os.environ["CCP4"],"lib","qt4","plugins"))

    def MyExit():
      print "Exiting"
      mainloops = []

    import atexit
    atexit.register(MyExit)

    m = MainLoop()
    import MainLoopContainer
    MainLoopContainer.MainLoopContainer.append(m)

    m.initialize(app)
    app.emit(QtCore.SIGNAL("ApplicationReady"), (app))

    sys.exit(app.exec_())
