"""
     python/ui/ccp4i_database.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     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.
"""
# Handle communication with CCP4i database
# and sort out file names

from global_definitions import *
from PyQt4 import QtCore
import utils

#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class ccp4i_database(QtCore.QObject):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------

  insts = ''
#-----------------------------------------------------------------------
  def __init__(self):
#-----------------------------------------------------------------------
    QtCore.QObject.__init__(self,MAINWINDOW())
    ccp4i_database.insts=self
    self.directories = []
    self.projects = []
    self.mg_current_project = ''
    rv = self.load_ccp4i_directories()

#------------------------------------------------------------------------
  def open_directories_file(self,mode,**kw):
#------------------------------------------------------------------------
    import os
    import string
    import sys

    ccp4_dir =  utils.get_HOME()
    if  not os.path.exists(ccp4_dir): return [1,'ERROR No HOME/USERPROFILE directory '+ccp4_dir] 
    if string.find('win32',sys.platform)>=0:
      subd = 'CCP4'
      opsys = 'windows'
    else:
      subd = '.CCP4'
      opsys = 'unix'
    directories_def =  os.path.join (ccp4_dir,subd,opsys,'directories.def')
    if mode == 'w' and os.path.exists(directories_def):
      import time,shutil
      backup = directories_def + '.' + time.strftime('%y_%m_%d_%H-%M')
      shutil.copyfile(directories_def,backup)
      
    f = utils.openFile(directories_def,mode,overwrite = 'Overwrite')
    if not f:  return [1,'ERROR opening '+directories_def]
    return [0,f,opsys]

#------------------------------------------------------------------------
  def handle_projects(self,change_projects='',update='',current_project='',
                      **keywords):
#------------------------------------------------------------------------
    '''
    Interface to the projects and directories gui in ccp4i
    '''
    #print "handle_projects",update,current_project
    if change_projects:
      MGGUI().Send('Directories edit')
      return
    if update == '1':
      # Handle signal from GUI to say user has changed projects
      import copy
      previous_project = copy.deepcopy(self.mg_current_project)
      self.load_ccp4i_directories()

      # Temporary work-round for problems
      # current_project = 0

      
      if current_project:
        #print "previous_project",previous_project,"current_project",current_project
        # Changed current project - if we are saving status on a
        # per-project basis then load the new current_project status
        if not PM('save_session_options').get('save_projects') or \
           current_project == previous_project : return
        import os
        # First save the previous project status
        filename = utils.get_filename( previous_project , \
                 os.path.join('CCP4_DATABASE','mg_exit_status.pkl')) 
        HISTORY().save_status(filename=filename,overwrite='overwrite', \
           save_list = HISTORY().save_to_project)

        # Is there a project status file for the new project
        filename = utils.get_filename( current_project , \
                 os.path.join('CCP4_DATABASE','mg_exit_status.pkl'))
        if not os.path.exists(filename): return

        # Delete the existing data objects
        import dataobj
        dataobj.Apply(action='delete',exit='confirm')
        
        # Now restore the status for the new project
        HISTORY().restore_status(filename=filename,restore_data=1)
    
#------------------------------------------------------------------------
  def load_ccp4i_directories(self,time=''):
#------------------------------------------------------------------------
    '''
    Load the ccp4i directories.def file into a dictionary
    '''
    import string
    import re

    rv = self.open_directories_file('r',time='')
    if rv[0]: 
      print rv[1]
      return rv
    f,opsys = rv[1:]
    text = f.read()
    f.close()
    lines = string.split(text,'\n')

    array = {}
    directories = []
    projects = []
    self.header = []

    for line in lines:
      if len(string.strip(line))<=0:
        pass
      elif line[0]=='#':
        self.header.append(line)
      else:
        #print "line",line
        varname,line0 = string.split(line,' ',1)
        line0 = string.strip(line0)
        try:
          if line[0] != '"':
            dtype,line0 = string.split(line0,' ',1)
        except:
          # Fails if no type in the definition
          pass
        linetmp = string.strip(line0)
        if linetmp:
          if linetmp[0] == '"' and linetmp[-1] == '"':
            linetmp = string.strip(linetmp,'"')
                   
          other = 1
          for item in ['N_PROJECTS','PROJECT_ALIAS','PROJECT_PATH','N_DEF_DIRS','DEF_DIR_PATH','DEF_DIR_ALIAS']:
            if varname.count(item): other = 0
        else:
          other = 1
        if other:
          self.header.append(line)
        else:
          array[varname] = (linetmp)
        #print "array",varname,array[varname]


    if array.has_key('N_PROJECTS'):
      for n in range(1,int(array['N_PROJECTS'])+1):
        if array.has_key('PROJECT_ALIAS,'+str(n)) and \
              array.has_key('PROJECT_PATH,'+str(n)):
          path = array['PROJECT_PATH,'+str(n)]
          if opsys == 'windows' and not re.search(r'/$',path): path = path + '/'
          projects.append([array['PROJECT_ALIAS,'+str(n)],path])
    if array.has_key('N_DEF_DIRS'):
      for n in range(1,int(array['N_DEF_DIRS'])+1):
        if array.has_key('DEF_DIR_ALIAS,'+str(n)) and \
              array.has_key('DEF_DIR_PATH,'+str(n)):
          path = array['DEF_DIR_PATH,'+str(n)]
          if opsys == 'windows' and not re.search(r'/$',path): path = path + '/'
          directories.append([array['DEF_DIR_ALIAS,'+str(n)],path])

    #if array.has_key('MG_CURRENT_PROJECT') and \
    #       directories.has_key(array['MG_CURRENT_PROJECT']):
    #  self.mg_current_project = array['MG_CURRENT_PROJECT']

    if directories:
      self.directories = directories
    if projects:
      self.projects = projects
    return 0
    
#--------------------------------------------------------------------------
  def get_project_dir(self,project=''):
#--------------------------------------------------------------------------
    #print 'get_project_dir',project,self.projects, self.directories
    for proj in self.projects:
      if str(proj[0]) == str(project):
        return str(proj[1])
    for proj in self.directories:
      if str(proj[0]) == str(project):
        return str(proj[1])
    return ''

#--------------------------------------------------------------------------
  def get_current_project(self):
#--------------------------------------------------------------------------
    return ''


#--------------------------------------------------------------------------
  def getProjectsList(self,aliases=1,projects=1):
#--------------------------------------------------------------------------
    proj_list = []
    alias_list = []
    if projects:
      for proj in self.projects:
          proj_list.append(proj[0])
    if aliases:
      for proj in self.directories:
        #if not ['TEMPORARY'].count(proj[0]):
          alias_list.append(proj[0])
    proj_list.sort()
    alias_list.sort()
    return [ proj_list,alias_list]

#--------------------------------------------------------------------------
  def aliasForDir(self,dirn):
#--------------------------------------------------------------------------
    ii = self.projectDirIndex(dirn)
    if ii<0:
      return ''
    elif ii<len( self.projects ):
      return self.projects[ii][0]
    else:
      return self.directories[ii-len(self.projects)][0]

  
#--------------------------------------------------------------------------
  def projectDirIndex(self,dir):
#--------------------------------------------------------------------------
    import os
    #dir = os.path.abspath(dir)
    #print "projectMatchingDir",dir
    ii = -1
    for listing in [ self.projects,self.directories ]:
      for proj,proj_dir in listing:
        #if not ['TEMPORARY'].count(proj):
          ii = ii + 1
          #print "proj,proj_dir",proj,proj_dir,ii
          try:
            if utils.samefile(dir,proj_dir):
              return ii
          except:
            pass
    return -1

#--------------------------------------------------------------------------
  def projectAliasIndex(self,alias):
#--------------------------------------------------------------------------
    ii = -1
    for listing in [ self.projects,self.directories ]:
      for proj,proj_dir in listing:
        #if not ['TEMPORARY'].count(proj):
          ii = ii + 1
          #print "proj,proj_dir",proj,proj_dir,ii
          try:
            if proj == alias:
              return ii
          except:
            pass
    return -1
 
#--------------------------------------------------------------------------
  def edit_dir_alias(self,alias='',path=''):
#--------------------------------------------------------------------------
    self.load_ccp4i_directories()
    ii = self.projectAliasIndex(alias)
    if ii>=0 and ii<len(self.projects):
      self.projects[ii] = [alias,path]
      #return [1,'Can not change project directory '+alias+' - please use CCP4i']
    elif ii>0:
      #print 'edit_dir_alias changing directories',ii,len(self.projects),self.directories[ii-len(self.projects)]
      self.directories[ii-len(self.projects)] = [alias,path]
    else:
      self.directories.append([alias,path])
    self.emit(QtCore.SIGNAL('directoriesChanged'),alias)
    return [0,'']

#--------------------------------------------------------------------------
  def delete_alias(self,alias=''):
#--------------------------------------------------------------------------
    #print 'delete_alias',alias, self.projectAliasIndex(alias)
    if alias == 'TEMPORARY':
      return [1,alias+' alias can not be deleted']
    ii = self.projectAliasIndex(alias)
    if ii < 0:
      return [1,alias+' alias is not saved in the directories database']
    elif ii < len(self.projects):
      self.projects.pop(ii)
      #return [1,alias+' is a project directory and can not be deleted']
    else:
      #print 'delete_alias changing directories',self.directories[ii-len(self.projects)]
      self.directories.pop(ii-len(self.projects))
      #print 'delete_alias directories',self.directories
      
    self.emit(QtCore.SIGNAL('directoriesChanged'),alias)
    return [0,'']
    
  def add_quotes(self,alias):
    if alias.count(' '):
      return '"'+alias+'"'
    else:
      return alias
      
#--------------------------------------------------------------------------
  def write_ccp4i_directories(self):
#--------------------------------------------------------------------------
    import string
    text = ''
    for line in self.header:
      text = text + line +'\n'

    text = text + '%-30s_positiveint1      %s'%('N_PROJECTS',str(len(self.projects)))  + '\n' 
            # '%-30s%s'%('PROJECT_ALIAS,0','\"\"') + '\n' + \
            # '%-30s%s'%('PROJECT_PATH,0','\"\"') + '\n'
    n = 0
    for alias,path in self.projects:
      n = n + 1
      text = text + '%-30s_text      %s'%('PROJECT_ALIAS,'+str(n),self.add_quotes(alias)) + '\n' + \
                    '%-30s_dir      %s'%('PROJECT_PATH,'+str(n),self.add_quotes(path)) + '\n'

      
    text = text + '%-30s_positiveint1      %s'%('N_DEF_DIRS',str(len(self.directories)))  + '\n' 
            # '%-30s_text     %s'%('DEF_DIR_ALIAS,0','\"\"') + '\n' + \
            # '%-30s_dir     %s'%('DEF_DIR_PATH,0','\"\"') + '\n'
           
    n = 0
    for alias,path in self.directories:
      n = n + 1
      text = text + '%-30s_text      %s'%('DEF_DIR_ALIAS,'+str(n),self.add_quotes(alias)) + '\n' + \
                    '%-30s_dir      %s'%('DEF_DIR_PATH,'+str(n),self.add_quotes(path)) + '\n'


    #print 'write_ccp4i_directories',text

    rv = self.open_directories_file(mode='w')
    if not rv[0]:
      f = rv[1]
      try:
        f.write(text)
        f.close()
      except:
        return [1,'Error saving directories information']

    return [0,'']
