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

#
# Collection of utility functions - mostly for
# handling filenames and text
#

import sys
import os
from global_definitions import *

temporaryFiles = []

# Slightly modified from http://timgolden.me.uk/python/win32_how_do_i/see_if_two_files_are_the_same_file.html
def get_read_handle (filename):
  import win32file
  if os.path.isdir(filename):
    dwFlagsAndAttributes = win32file.FILE_FLAG_BACKUP_SEMANTICS
  else:
    dwFlagsAndAttributes = 0
  return win32file.CreateFile (
    filename,
    win32file.GENERIC_READ,
    win32file.FILE_SHARE_READ,
    None,
    win32file.OPEN_EXISTING,
    dwFlagsAndAttributes,
    None
  )

def get_unique_id (hFile):
  import win32file
  (
    attributes,
    created_at, accessed_at, written_at,
    volume,
    file_hi, file_lo,
    n_links,
    index_hi, index_lo
  ) = win32file.GetFileInformationByHandle (hFile)
  return volume, index_hi, index_lo

def files_are_equal (filename1, filename2):
  try:
    hFile1 = get_read_handle (filename1)
  except:
    return True
  try:
    hFile2 = get_read_handle (filename2)
  except:
    return True
  try:
    are_equal = (get_unique_id (hFile1) == get_unique_id (hFile2))
    hFile2.Close ()
    hFile1.Close ()
  except:
    return True
  return are_equal

def samefile(f1,f2):
  if sys.platform != 'win32':
    return os.path.samefile(f1,f2)
  else:
    return files_are_equal(f1,f2)

def deleteTemporaryFiles():
    for f in temporaryFiles:
       try:
         if os.path.isfile(f):
           os.remove(f)
       except:
         exc_type, exc_value = sys.exc_info()[:2]
         print "Failed to remove temporary file",f
         print exc_type, exc_value

def fixModelNumbers(ifname,ofname):
  """
  This tries to see if numbering models as in the PDB
  spec. fixes load errors.
  """
  f = open(ifname)
  lines = f.readlines()
  f.close()

  oldmodel = {}

  lnew = []

  imodel = 1
  for l in lines:
    if l.startswith("MODEL "):
      oldmodel[int(l.split()[1])] = imodel
      lnew.append("MODEL     %d\n"%imodel)
      imodel = imodel + 1
    else:
      lnew.append(l)

  # Now we need to change cispep cards

  of = open(ofname,'w')
  for l in lnew:
    if l.startswith("CISPEP"):
      if int(l[43:46]) == 0:
        of.write(l)
      else:
        if int(l[43:46]) in oldmodel:
          of.write("%s%3d%s" % (l[:43],oldmodel[int(l[43:46])],l[46:]))
    else:
      of.write(l)
  of.close()


#-------------------------------------------------------------------
def ReadCoorFile(molHnd,filename,fixElementNames=True):
#-------------------------------------------------------------------
    import tempfile
    if filename.lower().endswith('cif') or filename.lower().endswith('cif.gz'):
      return molHnd.ReadCoorFile(filename)
    RC = molHnd.ReadCoorFile(filename)
    if RC==18 or RC==16:
      print "Dodgy model lines? Attempting renumber."
      try:
        tfile = tempfile.NamedTemporaryFile(suffix='.pdb')
        tfname = tfile.name
        tfile.close()
        fixModelNumbers(filename,tfname)
        RC = molHnd.ReadCoorFile(tfname)
        temporaryFiles.append(tfname)
      except:
        print "Failed to create temporary file in utils.ReadCoorFile"
        return -1
    if RC:
      return RC
    try:
      tfile = tempfile.NamedTemporaryFile(suffix='.pdb')
      tfname = tfile.name
      tfile.close()
    except:
      print "Failed to create temporary file in utils.ReadCoorFile"
      return -1
    nfixed = 0
    if fixElementNames and hasattr(molHnd,"FixElementNames") and callable(molHnd.FixElementNames):
      try:
        nfixed = molHnd.FixElementNames();
      except:
        pass
    RC = molHnd.WritePDBASCII(tfname)
    if RC:
      print "Failed to write to temporary file in utils.ReadCoorFile"
      return RC
    temporaryFiles.append(tfname)
    return molHnd.ReadCoorFile(tfname)

#-------------------------------------------------------------------
def reportError(level,message):
#-------------------------------------------------------------------
  global preferences
  if level >= preferences['REPORT_LEVEL']:
    print message

#-------------------------------------------------------------------
def matchKeyword(input,keywords):
#-------------------------------------------------------------------
  if keywords.count(input):
    return [1,[keywords.index(input)]]
    
  l = len(input)
  ll = []
  i = -1
  for kw in keywords:
    i = i + 1
    if input == kw[0:l]: ll.append(i)
  return [len(ll),ll]

#----------------------------------------------------------------
def equivKeyword(input,keywords,equivs):
#----------------------------------------------------------------
  if keywords.count(input):
    i = keywords.index(input)
    return equivs[i]
  else:
    return ''
  
#----------------------------------------------------------------
def decimalPlaces(input,nd):
#----------------------------------------------------------------
  import string
  ss = str(input)
  tt = string.find(ss,'.')
  if tt>-1:
    tt = min(tt+nd+1,len(ss))
    return ss[0:tt]
  else:
    return tt

#-------------------------------------------------------------------
def splitWords0(inp_str):
#-------------------------------------------------------------------
  import re
  import string
  if not inp_str or len(inp_str) <= 0: return []
  words = []
  continu = 1
  while continu:
    fq=string.find(inp_str,'"')
    #print "fq",fq
    if fq<0:
      words.extend(splitWords(inp_str))
      return words

    if fq>0:
      words.extend(splitWords(inp_str[0:fq]))

    if fq==len(inp_str)-1:
      continu = 0
    else:
      lq = string.find(inp_str[fq+1:],'"')
      #print "lq",lq
      if lq<0:
        inp_str=inp_str[fq+1:]
      else:
        if len(words)>0 and words[-1][-1]=='=':
          words[-1] = words[-1] + inp_str[fq+1:fq+lq+1]
        else:
          words.append(inp_str[fq+1:fq+lq+1])
        #print "words",words
        if fq+lq+2<len(inp_str):
          inp_str = inp_str[fq+lq+2:]
        else:
          continu = 0

  return words

#-------------------------------------------------------------------
def splitWords(inp_str):
#-------------------------------------------------------------------
  import re
  import string
  if not inp_str or len(inp_str) <= 0: return []
  words = []
  for w in re.split('\s',inp_str):
    w = string.strip(w)
    if w: words.append(w)
  return words

#-----------------------------------------------------------------
def makeList(value,length):
#-----------------------------------------------------------------
  mm = []
  for i in range(0,length):
    mm.append(value)
  return mm

#------------------------------------------------------------------
def oneWord(input,tcl_safe=0,compress=1):
#------------------------------------------------------------------
  if not input: return input
  import re
  import string
  input = tclSafe(input)
  if compress:
    n = 1
    while n > 0:
      input,n = re.subn('  ',' ',input)
  return re.sub(' ','_',string.strip(input))

#------------------------------------------------------------------
def tclSafe(input):
#------------------------------------------------------------------
  if not input: return input
  input = str(input)
  import re
  input = re.sub('\[',r'\[',input)
  input = re.sub('\$',r'\$',input)
  input = re.sub('\"',r'\"',input)
  input = re.sub('\{',r'\{',input)
  input = re.sub('\}',r'\}',input)
  return input

#------------------------------------------------------------------
def msvcescape(arg):
#------------------------------------------------------------------
    import re
    #if sys.platform != 'win32': return arg
    # If arg contains no space or double-quote then
    # no escaping is needed.
    if not re.search(r'[ "]', arg):
        return arg
    # Otherwise the argument must be quoted and all
    # double-quotes, preceding backslashes, and
    # trailing backslashes, must be escaped.
    def repl(match):
        if match.group(2):
            return match.group(1) * 2 + '\"'
        else:
            return match.group(1) * 2
    return '"' + re.sub(r'(\*)("|$)', repl, arg) + '"'


#------------------------------------------------------------------
def environScratch():
#------------------------------------------------------------------
  '''
  Return a reasonable scratch directory
  '''
  import re
  scratch = os.environ.get('SCRATCH')
  if not scratch:
    scratch = os.environ.get('CCP4_SCR')
  if not scratch:
    if sys.platform== 'win32':
      if   os.path.exists('C:/Ccp4Temp') and  os.path.isdir('C:/Ccp4Temp'):
        scratch = 'C:/Ccp4Temp'
      else:
        scratch = os.environ.get('USERPROFILE')
    else:
      if os.path.exists('/tmp') and  os.path.isdir('/tmp'):
        scratch = '/tmp/'
      else:
        scratch = os.environ.get(get_HOME())

  #print "environScratch",scratch
  return scratch

  
#--------------------------------------------------------------
def fileRoot(file):
#--------------------------------------------------------------
  return os.path.splitext(os.path.basename(file))[0]
  
#-----------------------------------------------------------------
def openFile ( filename, mode, warning=0, message='',overwrite='query',exit=''):
#-----------------------------------------------------------------
    import string
    import re

    if mode == 'w' and os.path.exists(filename):
      if not os.path.isfile(filename):
        if warning:
          MGGUI().WarningMessage(filename +" already exists. " + message)
        return
      elif overwrite == 'query':
        rv = MGGUI().CreateGUIWindow ('overwrite','', [
            ['TITLE','Overwrite '+filename],
            ['RETURN','utils.openFile',
              ['RETURN_LIST','filename']],
            ['CENTRE','SCREEN'],
            ['DISPLAY','CHOOSEOPTION','confirm',
               [['TEXT','File exits: '+filename+'\\nDo you want to overwrite it?'],
               ['OPTIONS',['Quit','Overwrite']]]  ]
           ],block=20)
        #print "openFile rv",rv
        if rv.has_key('exit'): overwrite = string.lower(rv['exit'])

        if overwrite == 'Quit':
          return
        elif overwrite == 'Overwrite':
          #NEED TO DELETE FILE
          pass

    if ['win32'].count(sys.platform):
      if re.search('b',mode)<0:
        mode = mode + 'b'
    try:
      f = open(filename,mode)
    except:
      if warning:
        MGGUI().WarningMessage("Error opening file " + filename + message)
      return ""
    return f

#-----------------------------------------------------------------
def saveFile(filename,text='',text_list=[],warning=0,overwrite='query'):
#-----------------------------------------------------------------
   if os.path.exists(filename):
     mode = 'w+'
   else:
     mode = 'w'
   #print "saveFile mode",mode
   f = openFile(filename,mode,warning=warning,overwrite=overwrite)
   if not f: return 1

   # Try writing to file
   try:
     if text_list:
       f.writelines(text_list)
     elif text:
       f.write(text)
     f.close()
   except:
     if warning:
       MGGUI().WarningMessage("Error writing file " + filename)
     return 1

   
   return 0

#-------------------------------------------------------------------
def fileDate (filename):
#-------------------------------------------------------------------
  # Return test string for last acces time of a file
  import time

  if not os.path.exists(filename): return ''
  stat = os.stat(filename)
  if len(stat)<=7: return ''
  return time.ctime(stat[7])

#--------------------------------------------------------------------
def get_HOME():
#--------------------------------------------------------------------
  
  '''
  print "HOME", os.environ.get('HOME')
  print "HOMEDRIVE", os.environ.get('HOMEDRIVE')
  print "HOMEPATH",  os.environ.get('HOMEPATH')
  print "USERPROFILE", os.environ.get('USERPROFILE')

  # Expect HOME defined in LINUX and use it if exists in windows
  #homedir = os.environ.get('HOME')
  #if homedir and homedir != '' and os.path.exists(homedir):
  #  return homedir
  if sys.platform == 'win32':
    # Try using HOMEDRIVE & HOMEPATH
    if os.environ.get('HOMEDRIVE'):
      if  os.environ.get('HOMEPATH'):
        homedir = os.path.join(os.environ.get('HOMEDRIVE'), os.environ.get('HOMEPATH'))
      else:
        homedir = os.environ.get('HOMEDRIVE')
    else: 
      # Last ditch effort - use USERPROFILE
      homedir = os.environ.get('USERPROFILE')
    if homedir and os.path.exists(homedir):
      print "get_HOME",homedir
      return homedir

  # Arghh - no HOME
  return ""
  '''

  try:
    if sys.platform == 'win32':
      homedir = os.environ.get('USERPROFILE')
    else:
      homedir = os.environ.get('HOME')
  except:
    homedir = ''
  if homedir and os.path.exists(homedir):
    return homedir
  else:
    return ''
 
  
#----------------------------------------------------------------------
def get_CCP4MG():
#----------------------------------------------------------------------
  ccp4mg =  os.path.join (get_HOME(),'.CCP4MG2')
  if not os.path.exists(ccp4mg) and sys.platform == 'win32':
    ccp4mg =  os.path.join (get_HOME(),'CCP4MG2') 
  if not os.path.exists(ccp4mg):
    try:
      os.mkdir(ccp4mg)
    except:
      print "ERROR creating .CCP4MG directory"
      return ""

  # Make sure that we also have the subdirectories
  for subd in ['status','logs','data','auto_save','recover']:
    path =  os.path.join ( ccp4mg , subd )
    if  not os.path.exists(path):
      try:
         os.mkdir(path)
      except:
        print "ERROR creating subdirectories in ",ccp4mg
  for subd in ['monomer_library','picture_wizard_files']:
    path =  os.path.join ( ccp4mg ,'data', subd )
    if  not os.path.exists(path):
        try:
          os.mkdir(path)
        except:
          print "ERROR creating subdirectories in ",ccp4mg
  return ccp4mg

#------------------------------------------------------------------
def redirectOutput(name='ccp4mg'):
#------------------------------------------------------------------
  import time
  import redirect
  
  directory = get_CCP4MG()
  print "Redirecting output to ",os.path.normpath(os.path.join(directory,name+'_stdout.txt'))
  print "Redirecting errors to ",os.path.normpath(os.path.join(directory,name+'_stderr.txt'))
  print "Started at ",time.strftime('%c',time.localtime()); sys.stdout.flush()

  if not os.path.exists(directory):
    try:
      os.mkdir(directory)
    except:
      pass

  if os.path.exists(directory):
    sys.stdout = open(os.path.normpath(os.path.join(directory,name+'_stdout.txt')),'w')
    sys.stderr = open(os.path.normpath(os.path.join(directory,name+'_stderr.txt')),'w')
    if sys.platform == "win32":
      redirect.RedirectStdOut(os.path.join(directory,name+'_c_stdout.txt'),"wb")
      redirect.RedirectStdErr(os.path.join(directory,name+'_c_stderr.txt'),"wb")
    else:
      redirect.RedirectStdOut(os.path.join(directory,name+'_c_stdout.txt'),"a")
      redirect.RedirectStdErr(os.path.join(directory,name+'_c_stderr.txt'),"a")
  elif os.environ.has_key("HOMEDRIVE"):
    directory = os.environ["HOMEDRIVE"]
    sys.stdout = open(os.path.join(directory,name+'_stdout.txt'),'w')
    sys.stderr = open(os.path.join(directory,name+'_stderr.txt'),'w')
    if sys.platform == "win32":
      redirect.RedirectStdOut(os.path.join(directory,name+'_c_stdout.txt'),"wb")
      redirect.RedirectStdErr(os.path.join(directory,name+'_c_stderr.txt'),"wb")
    else:
      redirect.RedirectStdOut(os.path.join(directory,name+'_c_stdout.txt'),"a")
      redirect.RedirectStdErr(os.path.join(directory,name+'_c_stderr.txt'),"a")
  else:
    return
  print "Redirected output to ",os.path.normpath(os.path.join(directory,name+ "_stdout.txt"))
  print "Started at ",time.strftime('%c',time.localtime())
   
#----------------------------------------------------------------------
def printOutput(text,ifout=1):
#----------------------------------------------------------------------
  print text
  sys.stdout.flush()

#---------------------------------------------------------------
def safeFloat(inp=None,default=0.0):
#---------------------------------------------------------------
  if inp!=None:
    try:
      return float(inp)
    except:
      return default
  else:
    return default

#---------------------------------------------------------------
def safeInt(inp=None,default=0):
#---------------------------------------------------------------
  if inp!=None:
    try:
      return int(inp)
    except:
      return default
  else:
    return default

#----------------------------------------------------------------
def safeAscii(text):
#----------------------------------------------------------------
  try:
    import curses.ascii
  except:
    return [0,text]
  not_ascii = 0
  ascii_text = ''
  for item in text:
    try:
      if curses.ascii.isascii(item):
        ascii_text = ascii_text + item
      else:
        not_ascii = 1
    except:
      not_ascii = 1
  return [not_ascii,ascii_text]
  
#-----------------------------------------------------------------
def round (inp=0.0 , mult=100):
#-----------------------------------------------------------------
  return float(int(inp*mult))/mult

#------------------------------------------------------------------
def sliderResolution ( range=1.0 ):
#------------------------------------------------------------------
  # Return a slider resolution for given range
  power = 1
  gt =  range > pow(10.0,power)
  if gt:
    power = power+1
  else:
    power = power-1
  while (range > pow(10.0,power)) == gt:
    if gt:
      power = power+1
    else:
      power = power-1        
  if gt: power = power - 1
  #print "power",power
  # Aim for resolution = 0.01*range
  if range > 5.0*pow(10.0,power):
    resol = 2.0*pow(10.0,(power-2))
  else:   
    resol = 1.0*pow(10.0,(power-2))
  #print "resol",resol
  return resol

#---------------------------------------------------------------------
  def list_quat(q):
#---------------------------------------------------------------------
     from pygl_coord import doublea
     p1 = q.Getdval()
     a1 = doublea(4)
     a1 = a1.frompointer(p1)
     print a1[0],a1[1],a1[2],a1[3]


#-------------------------------------------------------------------------
def get_filename(DIR_filename='',filename='',default_dir=''):
#-------------------------------------------------------------------------

    if ['','INLINE'].count(DIR_filename):
      DIR_filename =  CCP4DATABASE().mg_current_project

    if DIR_filename == 'FULLPATH':
      if os.path.exists(filename): return filename
    elif DIR_filename == 'dotCCP4MG':
      path = os.path.join(self.get_CCP4MG(),filename)
      return path
    if DIR_filename:
      path = CCP4DATABASE().get_project_dir(DIR_filename)
      if path and os.path.exists(path):
        path = os.path.join(path,filename)
        if os.path.exists(path):
           return path
    if default_dir:
      #print "Checking",os.path.join(default_dir,os.path.basename(filename))
      path = os.path.join(default_dir,os.path.basename(filename))
      if os.path.exists(path): return path
    
    import presentation
    for presobj in presentation.presentation.insts:
        if presobj.identifier == DIR_filename and \
                         os.path.exists(presobj.master_dir):
          path = os.path.join( presobj.master_dir, filename)
          #print "get_filename project_name", presobj.project_name, path
          return path

    # Nothing matched ....
    return filename

#-------------------------------------------------------------------------
def get_project(filename=''):
#-------------------------------------------------------------------------
    if filename == "":
      return ['FULLPATH',filename,filename]
    
    dir,filn = os.path.split(filename)
    if dir == '' or not os.path.isdir(dir):
       return ['FULLPATH',filename,filename]
    alias = CCP4DATABASE().aliasForDir(dir)
    if alias:
      return [alias,filn,filename]
    else:
      return ['FULLPATH',filename,filename]


  
#--------------------------------------------------------------------------
def copyTutorialData():
#--------------------------------------------------------------------------
    import re
    tutorial =  os.path.join (get_HOME(),'ccp4mg_tutorial')
    tut_text = re.sub(r'\\','/',tutorial)
    if  not os.path.exists(tutorial):
      try:
        os.mkdir(tutorial)
        text = 'Creating directory\n'+tut_text+'\nThis directory will contain a selection of files to use for the CCP4mg tutorials'
      except:
        return 'Error creating directory\n'+tutorial+'\\nNo data copied'
    else:
       text = 'Updating data files in existing directory\n'+tut_text+'\nThis directory will contain a selection of files to use for the CCP4mg tutorials'
    import glob
    import shutil
    source = (os.path.join(os.environ["CCP4MG"],'tutorial','data'))
    files = glob.glob(os.path.join(source,'*'))
    #print "files",files
    for file in files:
      if os.path.isfile(file):
        dst = os.path.join(tutorial,os.path.split(file)[1])
        #print "file",file
        #print "dst",dst
        if not os.path.exists(dst): shutil.copyfile(file,dst)
      if os.path.isdir(file):
        dstdir = os.path.join(tutorial,os.path.split(file)[1])
        if not os.path.exists(dstdir): os.mkdir(dstdir)
        files0 = glob.glob(os.path.join(file,'*'))
        for file0 in files0:
          if os.path.isfile(file0):
            dst = os.path.join(dstdir,os.path.split(file0)[1])
            if not os.path.exists(dst): shutil.copyfile(file0,dst)
    return text

#--------------------------------------------------------------------
def dict_diffs0(d1,d2):
#--------------------------------------------------------------------
  # list differences between two dictionaries
  # assume d1 is the old status and d2 is the new status
  k1 = d1.keys()
  k2 = d2.keys()
  diff = {}
  for item in k2:
    if ( not k1.count(item)) or d1[item] != d2[item]:
      diff[item] = d2[item]
  return diff

#--------------------------------------------------------------------
def dict_diffs(d1={},d2={},errcodes={}):
#--------------------------------------------------------------------
  rv=0
  diff =  {}
  minus_diff = {}
  k1 = d1.keys()
  k2 = d2.keys()
             
  for item in k2:
    if  (not k1.count(item)) or d1[item] != d2[item]:
      diff[item] = d2[item]
      rv = max(rv,errcodes.get(item,1))
      
  for item in k1:
    if not k2.count(item):
      minus_diff[item] = d1[item]
      rv = max(rv,errcodes.get(item,1))

  return (rv,diff,minus_diff)

#-----------------------------------------------------------
def dict_add(d1={},d2={},minus_d2={}):
#-----------------------------------------------------------
  
    k1 = d1.keys()
    k2 = d2.keys()
    mk2=minus_d2.keys()

    for item in k2:
      if k1.count(item) and mk2.count(item):
        if d1[item] == minus_d2[item]:
          d1[item] = d2[item]
          #print "dict_add", item,  d1[item]
      else:
        d1[item] = d2[item]
        #print "dict_add", item,  d1[item]
    
    return d1

#-------------------------------------------------------------------
def copy_data_file(filename='',dir='',overwrite=1):
#-------------------------------------------------------------------
    import shutil
    if os.path.exists(filename):
      newfile = os.path.join(dir,os.path.split(filename)[1])
      if not (os.path.exists(newfile) or overwrite) and not samefile(filename,newfile):
        try:
          shutil.copy( filename, dir)
        except:
          return [1,['Error attempting to copy '+filename+ ' to '+dir],[]]
    else:
      return [1,['File does not exists '+filename],[]]
    return [0,[],[newfile]]


#--------------------------------------------------------------------
def compress(filelist=[],compress_file='',uncompress=0):
#--------------------------------------------------------------------
  import gzip
  if not uncompress:
    try:
      out = gzip.open(compress_file,'wb')
      for file in filelist:
        inp = open(filn,'rb')
        out.write(inp.read())
        inp.close()
    except:
      MGGUI().WarningMessage('Error saving data to file '+compress_file)
      return
    try:
      out.close()
    except:
      pass
  else:
    try:
      input = gzip.open(compress_file)
      uncomp_output = open(filn,'wb')
      uncomp_output.write(input.read())
    except:
      MGGUI().WarningMessage('Error saving data to file '+filn)
      return

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

#-------------------------------------------------------------------
def unzip(zip_file=''):
#-------------------------------------------------------------------
    import zipfile
    dir_path = os.path.dirname(zip_file)
    #print 'utils.unzip',zip_file,dir_path
    try:
      z = zipfile.ZipFile(zip_file,"r")
      namelist = z.namelist()
      z.extractall(dir_path)
      z.close()
    except:
      return [1,'Can not extract from zip file '+zip_file]

    #print 'utils.unzip namelist',dir_path,namelist
    path = os.path.join(dir_path,os.path.split(namelist[0])[0])
    #print 'utils.unzip',path
    return [0,path]

#-------------------------------------------------------------------
def ZipAFile (filelist=[],zip_file='',unzip=0,path=''):
#--------------------------------------------------------------------
  import zipfile
  if not unzip:
    if os.path.exists(zip_file): os.remove(zip_file)
    try:
      out = zipfile.ZipFile(zip_file,"w")
    except:
      return (1,'Error opening zip file: '+zip_file)
    for file in filelist:
      file = os.path.abspath(file)
      top_path = os.path.dirname(file)
      if os.path.isfile(file):
        AddToZip([out,top_path],'',[file])
      else:
        os.path.walk(file,AddToZip,[out,top_path])

    return [0,'']
  else:
    if not path or not os.path.exists(path) or not os.path.isdir(path):
       #GUI.GUI.insts.WarningMessage('Error unzipping data to directory '+path)
       return [1,'Output directory '+path+' does not exists']
    isdir = os.path.isdir
    join = os.path.join
    norm = os.path.normpath
    split = os.path.split
    #try:
    if not os.path.exists(zip_file):
      return [1,'Zip file does not exist: '+zip_file]
    try:
      input = zipfile.ZipFile(zip_file)
    except:
      return [1,'Error opening zip file: ' + zip_file]
    #print "input",input
    for each in input.namelist():
      #print "each",each
      if not each.endswith('/'):
        root, name = split(each)
        directory = norm(join(path, root))
        if not isdir(directory):
          try:
            os.makedirs(directory)
          except:
            pass
        filn = join(directory, name)
        if not os.path.exists(filn):
          ff = open(filn, 'w')
          ff.write(input.read(each))
          ff.close()
    input.close()
    return [0,'']
        
    #except:
      #MGGUI().WarningMessage('Error saving data to file ')
    #  return

    
#------------------------------------------------------------------------    
def AddToZip( out, dir_path, names):
#------------------------------------------------------------------------
  import zipfile,string
  outfile,top_path = out
  #print "AddToZip dir_path",dir_path,'top_path',top_path
  for name in names:
    filn = os.path.join(dir_path,name)
    if os.path.isfile(filn)==1:
      outfile.write(filn,filn[len(top_path)+1:],zipfile.ZIP_DEFLATED)
    else:
      pass

#-------------------------------------------------------------------
def gunzipToNamedFile(fname):
#-------------------------------------------------------------------
             import gzip
             import tempfile
             try:
               f = gzip.open(fname)
               data = f.read()
               f.close()
             except:
               return ''
             dirname = os.path.dirname(fname)
             # Now there could be a problem here when restoring status.
             # If user opens a file from a read-only location
             # the file will be unzipped into a temporary directory.
             # We hope that temporary directory/file do not disappear.
             bn = os.path.splitext(os.path.basename(fname))[0]
             try:
               newFile = os.path.join(dirname,bn)
               tf = open(newFile,"w+b")
               tf.write(data)
               tf.close()
             except:
               d = tempfile.mkdtemp()
               newFile = os.path.join(d,bn)
               tf = open(newFile,"w+b")
               tf.write(data)
               tf.close()
             print "gunzipped input file to",newFile
             return newFile

#-------------------------------------------------------------------
def remove_file(path='',err_message=''):
#-------------------------------------------------------------------
  from PyQt4 import QtCore
  app = QtCore.QCoreApplication.instance()
  try:
    if app:
      app.emit(QtCore.SIGNAL("DeletingFile"),path)
    os.remove(path)
  except:
    print "ERROR deleting",path,err_message

#----------------------------------------------------------------------
def remove_directory(path):
#----------------------------------------------------------------------
  os.path.walk(path,rem_dir,'')

def rem_dir(nowt,top,names):
  for name in names:
    path = os.path.join(top,name)
    if os.path.isfile(path):
      os.remove(path)
    else:
      os.rmdir(path)


#-------------------------------------------------------------------
def picture_defn_item(item_name,value,pretty_print,indent=10,style='method',dict_order=[]):
#-------------------------------------------------------------------
  import types
  from PyQt4 import QtCore
  spaces = '                                                         '
  if type(value) == QtCore.QString:
    value = str(value.toUtf8())
  if isinstance(value,types.DictType):
    # Keep space on end of next line in case value =={} and so
    # jump straight to writing the close brace
    if style == 'method':
      stream =  '\n'+spaces[0:indent]+ item_name+ ' =  { '
    else:
      stream =  '\n'+spaces[0:indent]+ "'" +item_name+ "' :  { "
    if not dict_order: dict_order=value.keys()
    
    for key in dict_order:
      if value.has_key(key):
        if isinstance(value[key],types.FloatType):
          stream = stream + '\n'+spaces[0:indent+15]+"'"+key+"' : " + \
             str(value[key])+','
        elif isinstance(value[key],types.ListType):
          stream = stream + '\n'+spaces[0:indent+15]+"'"+key+"' : [ "
          for item in value[key]:
            stream = stream + '\n'+spaces[0:indent+30]+ \
                     pretty_print.pformat(item)+','
          stream =  stream[0:-1]+' ],'
            
        elif isinstance(value[key],types.DictType):
          stream = stream + picture_defn_item(key,value[key],pretty_print,indent=indent+15,style='dict')
          #print "picture_defn_item list key",key
          #stream = stream + '\n'+spaces[0:indent+15]+"'"+key+"' : {"
          #for key1,value1 in value[key].items():
          #  stream = stream + '\n'+spaces[0:indent+25]+"'"+key1+"' : " + \
          #             str(value1)+','\
                      
          #stream =  stream[0:-1]+'  },'
            
        else:
          stream = stream + '\n'+spaces[0:indent+15]+"'"+key+"' : " + \
             pretty_print.pformat(value[key])+','
    stream = stream[0:-1]+'  },'
    
  elif style == 'method':
    if  isinstance(value,types.FloatType):
      stream =  '\n'+spaces[0:indent]+ item_name+ ' = ' +str(value)+','
    else:
      stream =  '\n'+spaces[0:indent]+ item_name+ ' = ' +\
                 pretty_print.pformat(value)+','
  else:
    if  isinstance(value,types.FloatType):
      stream = '\n'+spaces[0:indent]+"'"+item_name+"' : " + str(value)+','
    else:
      stream = '\n'+spaces[0:indent]+"'"+item_name+"' : " + \
              pretty_print.pformat(value)+','

  return stream


#-------------------------------------------------------------------------
def check_filename(filename=[]):
#-------------------------------------------------------------------------
    import types
    if isinstance(filename,types.StringType):
      path,filn = os.path.split(filename)
      alias = CCP4DATABASE().aliasForDir(path)
      if alias:
        filename = [alias,filn,filename]
      else:
        filename = ['FULLPATH',filename,filename]

    # Do we have a good full path name for the file - if so use that
    # and try to find correct directory alias
    if os.path.exists(filename[2]):
      dir_alias = CCP4DATABASE().aliasForDir(os.path.split(filename[2])[0])     
      if dir_alias:
        filename[0] = dir_alias
        filename[1] = os.path.split(filename[2])[-1]
      else:
        filename[0] = 'FULLPATH'
        filename[1] = filename[2]
      #print 'check_filename full path exist',filename
      return filename
        
    # We are trying to find the file using the directory alias
    # If the directories info does not add up just say its 'FULLPATH'
    dir_path = CCP4DATABASE().get_project_dir(filename[0])
    if dir_path:
      file_path = os.path.join(dir_path,os.path.split(filename[1])[-1])
      if os.path.exists(file_path):
        filename[1] = os.path.split(filename[1])[-1]
        filename[2] = file_path
        #print 'check_filename file in alias dir',filename
        return filename


    # Does if exist? If not then try the home directory
    # and the current working directory
    for file_path in [
            os.path.join(get_HOME(),filename[1]),
            os.path.join(os.getcwd(),filename[1]) ]:
      if os.path.exists(file_path):
        filename[0] = 'FULLPATH'
        filename[2] = file_path
        return filename


    return filename


def parseVersion(restore_from_version):
  if not restore_from_version:
    return []
  else:
    try:
        vl = restore_from_version.split('.')
        vl.extend(['0','0'])
        ivl = []
        for item in vl[0:3]:
          ivl.append(safeInt(item,0))
        return ivl
    except:
      return []
