"""
     python/ui/web.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009 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.
"""
from global_definitions import *

#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
class web:
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
  insts = None

  def __init__(self):
    import sys
    web.insts = self
    self.scheduler = None
    if sys.platform == 'win32':
      self.browserlist = ['netscape','firefox','explorer']
    elif sys.platform == 'darwin':
      self.browserlist = ['netscape','firefox','open']
    else:
      self.browserlist = ['netscape','firefox','konqueror']

    import services
    self.params = services.ParamsManager ( \
          name='web_address', \
          title='Browser/Web Tools', \
          gui=['internal','browser','browser_command', 'EBI_Download_PDB','EBI_OCA','RCSB_Search','RCSB_Download_PDB','PDBJapan_Download_PDB','PDBJapan_Search'], \
        default = {
      'internal' : 1,
      'browser' : self.set_default_browser(),
      'browser_command' : '',
      'EBI_OCA' :  "http://www.ebi.ac.uk/msd-srv/msdlite/index.html",
      'RCSB_Search': "http://www.rcsb.org/pdb",
      'RCSB_Download_PDB': "'http://www.rcsb.org/pdb/cgi/export.cgi/' + pdbid + '.pdb?job=download;pdbId=' + pdbid +';opt=show;format=PDB;pre=1&compression=gz'" ,
      'EBI_Download_PDB' : "'ftp://ftp.ebi.ac.uk/pub/databases/msd/pdb_uncompressed/pdb'+pdbid+'.ent' " ,
      'PDBJapan_Download_PDB' : "'ftp://www.pdbj.org/pdb_nc/pdb'+pdbid+'.ent'" ,      'PDBJapan_Search' : "http://pdbjs3.protein.osaka-u.ac.jp/xPSSS/index.html" }, \
      #'EBI_Download_PDB' : "'http://oca.ebi.ac.uk/oca-bin/send-x-pdb?id=' + pdbid " ,
        definition = {
             'internal' : [ 'bool', 'Use internal browser (Linux only)'],
             'browser':  [str,'Web browser',['TYPEDEF','menu',self.browserlist,self.browserlist]], 
             'browser_command':  [str,'Browser executable path'], 
             'EBI_OCA' : [str,'EBI OCA search page'], \
             'RCSB_Search' : [str,'RCSB search page'], \
             'RCSB_Download_PDB' : [str,'RSCB PDB download command'] ,
             'EBI_Download_PDB' : [str,'EBI PDB download command'] ,
             'PDBJapan_Download_PDB' : [str,' PDBJapan download command'], 
             'PDBJapan_Search' : [str,' PDBJapan search page'] 
             }, \
        help = 'web' )
    self.default_server = 'EBI'


    
      
#---------------------------------------------------------------------------
  def GetPDBFile(self,pdbid,server='EBI'):
#---------------------------------------------------------------------------
    import urllib
    import socket
    import timeoutsocket
    
    if server == 'RCSB':
      exec "urlname = "+self.params.params['RCSB_Download_PDB']
    elif server == 'EBI':
      exec "urlname = "+self.params.params['EBI_Download_PDB']
    elif server == 'PDBjapan':
      exec "urlname = "+self.params.params['PDBJapan_Download_PDB']

    #print "server",server,"urlname",urlname
    
    ret = []
    dto = timeoutsocket.getDefaultSocketTimeout()
    timeoutsocket.setDefaultSocketTimeout(10)
    try:
      try:
        url = urllib.urlopen(urlname)
        pdbdata = url.read()
        #print "pdbdata",pdbdata
        url.close()
      except socket.error, msg:
        #print "timeout"
        ret = [2,"Timeout waiting?"]
      except:
        ret = [3,'No data called '+pdbid+'?']
    finally:
      timeoutsocket.setDefaultSocketTimeout(dto)
      
    if not ret:
      return [0,pdbdata]
    else:
      return ret


#--------------------------------------------------------------------
  def downloadpdb_handler ( self, ID='',local_file='', DIR_local_file='',  \
                    view_server='',server='',**keywords):
#--------------------------------------------------------------------
    import string
    import utils

    if view_server:
      if server == 'EBI':
        self.launch_browser( url=self.params.params['EBI_OCA'],internal=-1)
      elif server == 'RCSB':
        self.launch_browser( url=self.params.params['RCSB_Search'],internal=-1)
      else:
        self.launch_browser( url=self.params.params['PDBJapan_Search'],internal=-1)
        
    if ID and not local_file:
      ID=string.lower(string.strip(ID))
      name = string.split(ID,',')[0]+'.pdb'
      fullname = utils.get_filename('',name)
      MGGUI().insts.UpdateGUIWindow ('downloadpdbfile', [
         ['OBJECT','local_file',
           ['CONFIGURE',
             ['filename',name],
             ['fullname',fullname]]] ])

#-----------------------------------------------------------------------
  def downloadpdbfile (self,server='EBI',ID='',local_file='', DIR_local_file='',
      compress=1, drawing_style='all_atoms',show_gui_on_loading='',
                       exit='', **keywords):
#-----------------------------------------------------------------------
    import utils
    if exit == 'dismiss': return
    if ['EBI','PDBjapan'].count(server): compress = 0
    if ['EBI','PDBjapan','RCSB'].count(server): self.default_server = server

    if not ID:
      MGGUI().WarningMessage('You must enter a four-letter code', \
                                   parent='downloadpdbfile')
      return

    import gzip
    import string
    import os
    import re

    # Remove the '.pdb'
    ID=string.lower(string.strip(ID))
    ID = string.split(ID,'.')[0]

    if not local_file:
      local_file = ID+'.pdb'
      DIR_local_file = CCP4DATABASE().get_current_project()

    filn = utils.get_filename(DIR_local_file,local_file)
    #print "filn",filn
    
    if os.path.exists(filn):
      MGGUI().WarningMessage('A file called '+filn+' already exists', \
                                   parent='downloadpdbfile')
      return

    status,pdbdata = self.GetPDBFile(ID,server=server)
    if status:
      MGGUI().WarningMessage(pdbdata,parent='downloadpdbfile')
      return
    if not pdbdata:
      MGGUI().WarningMessage('No data returned from server', \
                                   parent='downloadpdbfile')
      

    if compress:
      
      try:
        output = utils.openFile(filn+'.gz','wb')
        output.write(pdbdata)
        output.close()
      except:
        MGGUI().WarningMessage('Error saving compressed data to file ' \
                                   +filn+'.gz',parent='downloadpdbfile')
        return
      try:
        input = gzip.open(filn+'.gz')
        uncomp_output = open(filn,'wb')
        uncomp_output.write(input.read())
      except:
        MGGUI().WarningMessage('Error saving data to file '+filn, \
                                   parent='downloadpdbfile')
        return

      try:
        input.close()
        uncomp_output.close()
        os.remove(filn+'.gz')
      except:
        pass

    else:
      # Try saving uncompressed data
      if re.search("<HTML>",pdbdata):
        MGGUI().WarningMessage('Error reported from download site', \
                                   parent='downloadpdbfile')
        return

        
      try:
        output = utils.openFile(filn,'w')
        output.write(pdbdata)
        output.close()
      except:
        MGGUI().insts.WarningMessage('Error saving data to file ' \
                                   +filn,parent='downloadpdbfile')
        return
    
    # Only delete the GUI window when we're sure it all worked
    MGGUI().DeleteGUIWindow ('downloadpdbfile')

    # Load the data from the local PDB file
    import model
    model.openpdbfile(pdbin=local_file,DIR_pdbin=DIR_local_file,
      drawing_style=drawing_style,show_gui_on_loading=show_gui_on_loading,
                      exit=exit)

#---------------------------------------------------------------------------
  def set_default_browser(self):
#---------------------------------------------------------------------------
    import sys
    import re
    import string
    import glob
    import os
    
    separator = ':'
    if re.search('darwin',sys.platform):
      return 'open'   
    elif re.search('win',sys.platform):
      return 'explorer'
    else:
      browser_list =  ['firefox','konqueror','mozilla','netscape']
      
    for browser in browser_list:
      for path in string.split(os.environ['PATH'],separator):
        if glob.glob(os.path.join(path,browser)):
          return browser

    else:
      # Looks bad but just try this
      return "netscape"

#-------------------------------------------------------------------------
  def launch_browser ( self, url = '', file = '', target ='',
           max_retry=0,retry=-1, internal = 0, **keywords) :
#-------------------------------------------------------------------------
    import os,sys,string

    # It should be..
    # internal == -1: Use external browser
    # internal == 1: Use internal browser
    # internal == 0: Check user preference
    
    if string.find(sys.platform,'nux')>0:
      if internal == 0: internal = self.params.params.get('internal')
    else:
      internal = -1
    #print "launch_browser internal",internal
    #print "launch_browser file",file,self.scheduler

    # First make sure we have a file to display
    if file:

      # Retry >0 implies launch_browser has
      # been invoked from the scheduler - we want to stop it if
      # file exists or we've tried max_retry times
      if self.scheduler and  (retry>max_retry or os.path.exists(file)):
          self.scheduler.RemoveTask(self.launch_browser,[], \
                    { 'file' : file,
                    'target' : target })

      if not os.path.exists(file):
        if retry<0 and self.scheduler:
          self.scheduler.AddTask(self.launch_browser,[], \
                  { 'file' : file,
                    'target' : target },
                     max_retry= max_retry-1 ) 
          return
        elif retry>max_retry or not self.scheduler:
          print "Error attempting to display file:",file,' file does not exist'
          return [1,'Error attempting to display file: '+file+ \
                      '\\n file does not exist']
        return



    if url:
     cmd = 'browser '+url
    elif file:    
     cmd = 'browser '+file

    # Default is send to internal (hv3) browser
    if internal>0:
      import guiUtils
      guiUtils.guiHelp(file=file)
      return
          
    args = []
    browser = self.params.params.get('browser')
    browser_command = self.params.params.get('browser_command')
    #print "browser_command",browser_command

    if sys.platform != 'win32':
      if not browser_command: browser_command = browser
      # The -url argument causes problems on Linux if the browser is
      # already open
      #if re.search('firefox|mozilla|netscape',browser_command) and not re.search('-url',browser_command):
      #    browser_command =browser_command+' -url'
      if url:
        cmd = browser_command +' '+url+' &'
      elif file:
        cmd = browser_command +' '+file
        if target and not ['open','firefox'].count(browser_command): cmd=cmd+'#'+target
        cmd = cmd + ' &'  
      print 'launch_browser cmd',cmd
      try:
        os.system(cmd)
      except:
        return [1,'Error launching '+browser+' browser']

    else:
      #Windows specific
      import _winreg
      import string
      import utils
      import re

      # Try to get browser executable from registry
      if not browser_command:
        key = None
        ii = -1
        trythese = ['HTTP','http','https']
        while key == None and ii < len(trythese):
          try:
            ii = ii+1
            key = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,trythese[ii]+'\\shell\\open\\command')
          except:
            key = None
          if key:
            browser_command = _winreg.QueryValueEx( key, "") [0]
        if not key or not browser_command:
          MGGUI().WarningMessage('Failed to find executable for browser'+browser+'//nPlease use the Preferences, Web Tools interface to choose another browser//n or enter the full path name for the executable')
          return
        if re.search('IREF|iref',browser_command) :
          browser = 'firefox'
        elif re.search('ETSC|etsc',browser_command) :
          browser = 'netscape'
        else:
          browser = 'explorer'
        print "launch_browser key",key,browser_command
        print 'treat as browser',browser
        
      comd_words = utils.splitWords0(browser_command)
      #print "comd_words",comd_words
      browser_command = string.strip(comd_words[0],'"')
      for word in comd_words[1:]:
        if re.match('%',word)<0:
          args.append(string.strip(word,'"'))

      if ['firefox','netscape','mozilla'].count(browser):
        if not args.count('-url'):args.append('-url')
        file = re.sub(r'\\',r'/',file)
        if not re.match('file',file): file = 'file:///'+file
      args.append(utils.msvcescape(file))

      print "launch browser cmd",browser_command,"args",args

      try:
        os.spawnv(os.P_NOWAIT,browser_command,args)
      except:
        return [2,'Error launching '+browser]

    return [0,'']

  
  def display_ani_gif (self, file = '', internal=1, **keywords ) :

     import sys,string
     if string.find(sys.platform,'nux')>0 :
       MGGUI().Send('run_anigif '+file)
     else:
       # Try using external browser
       self.launch_browser(file=file,internal = -1)