
"""
     utils/startup.py.py: CCP4 GUI Project
     Copyright (C) 2010 University of York

     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.
"""

'''
    Liz Potterton Feb 2010 - Some minimal functionality to bootstrap program startup
'''


import os,sys,atexit
from PyQt4 import QtCore, QtGui

def getCCP4I2Dir(up=1):
  import os,sys
  target = os.environ.get('CCP4I2_TOP',None)
  #print 'startup.getCCP4I2Dir environ',target
  if target is not None:
    return os.path.abspath(target)
  else:
    target = os.path.join(os.path.abspath(sys.argv[0]),"..")
    abstarget = os.path.abspath(target)
    splittarget = abstarget.split('/')
    #print 'startup.getCCP4I2Dir splittarget ',splittarget
    if splittarget.count('ccp4i2'):
      splittarget.reverse()
      #print 'startup.getCCP4I2Dir reverse splittarget ',splittarget
      up = splittarget.index('ccp4i2')
    while up>0:
      abstarget = os.path.dirname(abstarget)
      up = up -1
    #print 'startup.getCCP4I2Dir Environment variable CCP4I2_TOP not defined - trying ',abstarget
    return abstarget

def setupEnvironment(path=''):
  if not path: path = getCCP4I2Dir()
  os.environ["CCP4I2_TOP"] = path
	
def setupPythonpath(top='',mode='qtgui'):
  #print 'setupPythonpath',mode
  import glob
  if mode == 'qtgui':
    'Setting Python path for graphical mode'
  else:
    'Setting  Python path for non-graphical mode'
  if not top: top = getCCP4I2Dir()
  for item in ['server_interface']:
    dirList = glob.glob(os.path.join(top,'custom_code',item,'*'))
    for dr in dirList:
      sys.path.insert(0,dr)
      #if dr[-4:] != 'demo': sys.path.insert(0,dr)
  for item in ["model","report","dbapi","lib","core","utils","googlecode"]:
    sys.path.insert(0,os.path.join(top,item))
  sys.path.insert(0,top)
  
  if ['qtcore','qtgui'].count(mode)>0:
    for item in ["pimple","qtcore"]:
      sys.path.insert(0,os.path.join(top,item))

      
  if mode == 'qtgui':
    sys.path.insert(0,os.path.join(top,"qtgui"))
    taskDirs = glob.glob(os.path.join(top,"tasks","*"))
    #print 'setupPythonpath taskDirs',taskDirs
    sys.path.extend(taskDirs)
    
  scriptDirs = glob.glob(os.path.join(top,"wrappers","*","script"))
  scriptDirs.extend(glob.glob(os.path.join(top,"wrappers2","*","script")))
  scriptDirs.extend(glob.glob(os.path.join(top,"pipelines","*","script")))
  scriptDirs.extend(glob.glob(os.path.join(top,"pipelines","*","wrappers","*","script")))
  scriptDirs.extend(glob.glob(os.path.join(top,"pipelines","*","gui")))
  sys.path.extend(scriptDirs)

  
def setupGuiPluginsPath(top=''):
  # Add all ccp4i2/tasks/* directories to search path
  if not top: top = getCCP4I2Dir()
  import glob
  pluginsSearchPath = [os.path.join(top,"tasks")]
  pluginDirs = []
  for searchPath in pluginsSearchPath:
    pluginDirs.extend(glob.glob(os.path.join(searchPath,'*')))
  for pD in pluginDirs:
    sys.path.append(pD)
                    
def setupPluginsPath(top=''):
  # Add all ccp4i2/wrappers/* and ccp4i2/plugins/* directories to search path
  if not top: top = getCCP4I2Dir()
  import glob
  pluginsSearchPath = [ os.path.join(top,'wrappers'),
                       os.path.join(top,'pipelines')]
  plineWraps = glob.glob(os.path.join(top,'pipelines','*','wrappers'))
  pluginsSearchPath.extend(plineWraps)
  pluginDirs = []
  for searchPath in pluginsSearchPath:
    pluginDirs.extend(glob.glob(os.path.join(searchPath,'*')))
  for pD in pluginDirs:
    sys.path.append(os.path.join(pD,'script'))
  

def testForCCP4Environment():
  import os
  ccp4_env = os.environ.get('CCP4','NOT SET')
  print 'Using CCP4 from: ',ccp4_env
  if ccp4_env == 'NOT SET':
    return False
  else:
    return True


def startGraphics():
  import sys,CCP4Config
  app = CGuiApplication(sys.argv)
  CCP4Config.CONFIG().set('graphical',True)
  CCP4Config.CONFIG().set('qt',True)
  return app

def setQtWidgetStyle():
  from PyQt4 import QtGui
  import CCP4Modules
  try:
      factory = QtGui.QStyleFactory()
      stylePref = CCP4Modules.PREFERENCES().WINDOWS_STYLE.__str__()      
      style = factory.create(stylePref)
      CCP4Modules.QTAPPLICATION().setStyle(style)
  except Exception as e:
      print 'ERROR setting window style..'
      print e

def startBrowser(args,app=None,splash=None):
  #print 'startBrowser args',args
  # KJS : Removed Linux check. Why it's in here is unclear.
  # if sys.platform == "linux2": win = QtGui.QWidget(); splash.finish(win); splash.show()
    
  config = loadConfig()
  config.set('graphical',True)
  config.set('qt',True)

  kw = {'graphical' : True}
  ii = 0
  while ii < len(args):
    if args[ii] in ['-db']:
      if ii+1 < len(args):
        ii += 1
        kw['dbFileName'] = os.path.abspath(args[ii])
    elif args[ii] in ['-u','-user','-username']:
      if ii+1 < len(args):
        ii += 1
        kw['userName'] = args[ii]
    ii+=1
  
  import CCP4WebBrowser,CCP4CustomMimeTypes,CCP4Modules
  if app is None:
    app = CCP4Modules.QTAPPLICATION()
  startPrintHandler(app)

  CCP4WebBrowser.setupWebkit()
  pm = startProjectsManager(**kw)
  pm.startCheckForFinishedJobs()
  jc = startJobController()
  if kw.get('dbFileName',None) is not None: jc.setDbFile(kw['dbFileName'])

  la = CCP4Modules.LAUNCHER()
  print 'startup.startBrowser app',app
  setQtWidgetStyle()
  
  def closeHTTPServer(parent=None):
    # Called on exit to find and close all CHTTPServerThread threads
    import CCP4HTTPServerThread
    #sys.__stdout__.write('CCP4Utils/startup.closeHTTPServer\n');sys.__stdout__.flush()
    if CCP4HTTPServerThread.CHTTPServerThread.insts is not None:
      CCP4HTTPServerThread.CHTTPServerThread.insts.quitServer()

  app.connect(pm,QtCore.SIGNAL("doCheckForFinishedJobs"),pm.checkForFinishedJobs)

  # the aboutToQuit() signal does not work
  # atexit is too late to save status - 
  for func in (pm.Exit,jc.Exit,la.Exit,closeHTTPServer,sys.__stdout__.flush,sys.__stderr__.flush,CCP4Modules.PRINTHANDLER().exit):
  #  app.connect(app,QtCore.SIGNAL('aboutToQuit()'),func)
     atexit.register(func)
  

  startHTTPServer(parent=app)
  CCP4WebBrowser.restoreStatus()
  CCP4WebBrowser.applyCommandLine(args)
  import CCP4StyleSheet,CCP4WebView
  CCP4StyleSheet.setStyleSheet()
  CCP4WebView.setGlobalSettings()

  if hasattr(splash,"close"):
    splash.close()

def startDefEd():
  import CCP4Config
  pars = CCP4Config.CConfig(qt=True,graphical=True,developer=True)
  import CCP4DefEd
  defEd = CCP4DefEd.CDefEd()
  defEd.raise_()
  return defEd

def startJobController():
  import CCP4Modules
  print 'Starting Job Controller'
  jc = CCP4Modules.JOBCONTROLLER()
  jc.startTimer()
  print 'Starting Job Controller - DONE'
  jc.restoreRunningJobs()

  return jc
 
def startProjectsManager(dbFileName=None,checkForFinishedJobs=False,**kw):
  import CCP4Modules,CCP4ProjectsManager
  if CCP4ProjectsManager.CProjectsManager.insts is not None:
    print 'Attempting to start Project Manager for second time - should not do this!'
    return  CCP4ProjectsManager.CProjectsManager.insts
  else:
    print 'Starting Project Manager'
    if dbFileName is not None: print 'Using database file: ',dbFileName
    pm = CCP4Modules.PROJECTSMANAGER()
    db = startDb(pm,mode='sqlite',fileName=dbFileName,**kw)
    pm.setDatabase(db)
    if checkForFinishedJobs:pm.startCheckForFinishedJobs()
    print 'Starting Project Manager - DONE'
    return pm

def startDb(parent=None,fileName=None,mode='sqlite',userName=None,userPassword=None,**kw):
  import CCP4DbApi,CCP4ErrorHandling
  try:
    db = CCP4DbApi.CDbApi(parent=parent,fileName=fileName,mode=mode,createDb=True,userName=userName,userPassword=userPassword,loadDiagnostic=kw.get('loadDiagnostic',True))
  except CCP4ErrorHandling.CException as e:
    print 'startDb', e[0]['code'],kw.get('graphical',False)
    if e[0]['code'] == 121 and kw.get('graphical',False):
      try:
        import CCP4Utils,CCP4DbManagerGui
        currentUserName = CCP4Utils.getUserId()
        import CCP4DbManagerGui
        dialog = CCP4DbManagerGui.CChallengeUnknownUser(currentUserName=currentUserName)
        rv = dialog.exec_()       
      except:
         rv = False
      if rv:
        ownerName = dialog.getOwner()
        reset = dialog.getReset()
        try:
          db = CCP4DbApi.CDbApi(parent=parent,fileName=fileName,mode=mode,createDb=True,userName=ownerName,userPassword=userPassword)
        except:
          pass
        else:
          try:
            db.createUser(currentUserName)
          except:
            print 'Failed adding current user to database user list'
          if reset:
            try:
              db.updateUser(ownerName,newUserName=currentUserName)
            except CCP4ErrorHandling.CException as e:
              e.warningMessage(parent=parent)
          return db
    if kw.get('graphical',True):
      try:
         e.warningMessage(parent=parent)
      except:
         pass
      print e.report()
      print 'Please try removing $HOME/.CCP4I2/db directory so new database is created'
      if e[0]['code'] == 222:
        print 'In future updates to database schema will be handled better!'
      else:
        print 'Please report to ccp4@ccp4.ac.uk'
      sys.exit()

  except Exception as e:
    print e
    print 'Please try removing $HOME/.CCP4I2/db directory so new database is created'
    print 'Please report to ccp4@ccp4.ac.uk'
    sys.exit()
  return db

def loadConfig():
  import CCP4Config,CCP4Utils
  config = CCP4Config.CONFIG(os.path.join(CCP4Utils.getDotDirectory(),'configs','ccp4i2_config.params.xml'))
  return config


def  startHTTPServer(parent=None,port=None):
  import CCP4HTTPServerThread
  import CCP4Utils
  if port is None: port = CCP4HTTPServerThread.DEFAULT_PORT
  diry = os.path.join(CCP4Utils.getCCP4I2Dir(),'docs')
  t = CCP4HTTPServerThread.CHTTPServerThread(parent=parent,parentDir=diry,port=port)

  """
  def handleServerInsertFile(args):
    import CCP4Modules
    import CCP4DbApi
    import CCP4ModelData
    import CCP4XtalData

    filename,data,projectName = args
    print filename,projectName
    # These should throw wobblers somehow to *log file*. Not GUI.
    try:
      db = CCP4Modules.PROJECTSMANAGER().db()
    except:
      print "Failed to access CCP4i2 database"

    db.listProjects(True)

    try:
      pid = db.getProjectId(projectName)
    except:
      print "Failed to get project",projectName

    info = db.getProjectJobListInfo(projectName=projectName)
    print info

    jid1 =  db.createJob(pid,'File inserted from CCP4MG',status=CCP4DbApi.JOB_STATUS_FINISHED)
    print jid1
    jobNumber = db.getJobInfo(jid1,'jobnumber')
    print jobNumber
    relPath = 'CCP4_JOBS/job_%s' % jobNumber
    print relPath
    fo1 = CCP4ModelData.CPdbDataFile(project=projectName,relPath=relPath,baseName=os.path.basename(filename))
    print fo1
    #f1= db.createFile(jobId=jid1,fileObject=fo1,sourceFileName=os.path.join(CCP4Utils.getTestTmpDir(),'starting_data.seq'))

  if parent is not None:
    parent.connect(t,QtCore.SIGNAL('insertFileInDBRequest'),handleServerInsertFile)
  """

  t.start()
  #print 'Starting CCP4i2 HTTP server on port:',CCP4HTTPServerThread.HTTPThread().port
  return

def startPrintHandler(app):
  import sys
  from PyQt4 import QtCore
  import CCP4PrintHandler
  printHandler = CCP4PrintHandler.CPrintHandler(parent=app)
  try:
    printHandler.cleanupLogs()
  except Exception as e:
    print 'ERROR cleaning up print logs'
    print e
  # Do a getFileObject() here to ensure the filename is main_thread
  f = printHandler.getFileObject(thread=None,name='main_thread')
  sys.stdout = printHandler
  sys.stderr = printHandler
  app.connect(app,QtCore.SIGNAL('aboutToQuit()'),printHandler.exit)
  # Output version info to the print log
  

  
