"""
     CCP4CustomisationGui.py: CCP4 GUI Project
     Copyright (C) 2013 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.
"""

"""
     Liz Potterton July 2013 - create and manage customisations
"""

import os
from PyQt4 import QtGui,QtCore
import CCP4Data,CCP4Container
from CCP4ErrorHandling import *
from CCP4Modules import WEBBROWSER,PROJECTSMANAGER,DUMMYMAINWINDOW


class CCustomisationGui(QtGui.QDialog):

  insts = []
  
  def __init__(self,parent=None,mode=None,title=None,ifEdit=True,ifClone=True):
    if parent is None: parent = DUMMYMAINWINDOW()
    QtGui.QDialog.__init__(self,parent)
    CCustomisationGui.insts.append(self)
    self.mode = mode
    self.setWindowTitle(title)
    self.createWidget = None

    layout = QtGui.QGridLayout()
    self.setLayout(layout)
  
    self.customListView = CCustomListWidget(self)
    self.connect(self.customListView,QtCore.SIGNAL('itemDoubleClicked(QListWidgetItem*)'),self.handleDoubleClick)
    self.customListView.populate()
    self.layout().addWidget(self.customListView,1,0)

    butDef = [          ['New',self.handleNew,True,False],
                        ['Edit',self.handleEdit,True,False],
                        ['Clone',self.handleClone,True,False],
                        ['Export',self.handleExport,True,False],
                        ['Import',self.handleImport,True,False],
                        ['Delete',self.handleDelete,True,False],
                        ['Help',self.handleHelp,True,False]]
    if not ifClone: del butDef[2]
    if not ifEdit: del butDef[1]

    buttonLayout = QtGui.QVBoxLayout()
    for label,slot,enabled,default in butDef:
                       
      button =QtGui.QPushButton(self,text=label)
      button.setEnabled(enabled)
      if default: button.setDefault(True)
      buttonLayout.addWidget(button)
      self.connect(button,QtCore.SIGNAL('clicked()'),slot)
      
    self.layout().addLayout(buttonLayout,1,1)

    
  def done(self,r):
    try:
      CCustomisationGui.insts.remove(self)
    except:
      print 'Error in CCustomisationGui.done removing from insts list'
    print 'CCustomisationGui.done',r,CCustomisationGui.insts
    QtGui.QDialog.done(self,r)

  def manager(self):
    # Reimplement in sub-class
    return None

  def handleNew(self):
    pass

  def handleEdit(self,selected):
    print 'CCustomisationGui.handleEdit',selected
    pass

  def handleClone(self):
    selected = self.customListView.selectedItem()
    if selected is None: return
    if not hasattr(self,'cloneDialog'):
      self.cloneDialog = CCustomCloneDialog(self)
      self.connect(self.cloneDialog,QtCore.SIGNAL('clone'),self.handleClone2)
    self.cloneDialog.setSelected(selected)
    self.cloneDialog.show()
    self.cloneDialog.raise_()

  def handleClone2(self,original,new,ifEdit=True):
    try:
      self.manager().clone(original,new)
    except CException as e:
      e.warningMessage('Clone '+self.mode,'Error cloning '+original,parent=self)
      return
    if ifEdit: self.handleEdit(new)
  
  def handleDoubleClick(self,item):
    nameVar = item.data(QtCore.Qt.UserRole)
    name = nameVar.toString().__str__()
    self.handleEdit(selected=name)

  def handleExport(self):
    selected = self.customListView.selectedItem()
    if selected is None: return
    import CCP4FileBrowser,functools
    self.browser = CCP4FileBrowser.CFileDialog(self,
           title='Save '+self.mode+' to compressed file',
           filters= ['CCP4 '+self.mode+' (*.ccp4_'+self.mode+'.tar.gz)'],
           defaultSuffix='ccp4_'+self.mode+'.tar.gz',
           fileMode=QtGui.QFileDialog.AnyFile  )
    self.connect(self.browser,QtCore.SIGNAL('selectFile'),functools.partial(self.handleExport2,selected))
    self.browser.show()

  def handleExport2(self,selected,fileName):
    self.browser.hide()
    self.browser.deleteLater()
    del self.browser
    err = self.manager().export(selected,fileName)
    if err.maxSeverity()>SEVERITY_WARNING:
      err.warningMessage('Export '+self.mode,'Error creating compressed file',parent=self)
      
  def handleImport(self):
    import CCP4FileBrowser
    self.browser = CCP4FileBrowser.CFileDialog(self,
           title='Import '+self.mode+' compressed file',
           filters= ['CCP4 compressed '+self.mode+' (*.ccp4_'+self.mode+'.tar.gz)'],
           defaultSuffix='ccp4_'+self.mode+'.tar.gz',
           fileMode=QtGui.QFileDialog.ExistingFile  )
    self.connect(self.browser,QtCore.SIGNAL('selectFile'),self.handleImport1)
    self.browser.show()

  def handleImport1(self,fileName):
    self.browser.hide()
    self.browser.deleteLater()
    del self.browser
    #print 'handleImport1',fileName
    try:
      self.manager().testImport(fileName)
    except CException as e:
      if e.count(code=110) == 0:
        e.warningMessage('Error opening compressed '+self.mode+' file',parent=self)
      else:
        name = e[0]['details']
        self.importQuery = CCustomImportDialog(self,name,fileName)
        self.connect(self.importQuery,QtCore.SIGNAL('import'),self.handleImport2)
        self.importQuery.show()
    else:
      try:
        self.manager().uncompress(fileName,self.manager().getDirectory())
      except CException as e:
        e.warningMessage('Error importing '+self.mode,'Failed to write to '+self.mode+' directory',parent=self)

  def handleImport2(self,name,fileName,overwrite,rename):
    #print 'handleImport2',name,overwrite,rename
    if overwrite:
      self.manager().delete(name)
    self.manager().uncompress(fileName, self.manager().getDirectory(),rename=rename)
    
  def handleDelete(self):
    selected = self.customListView.selectedItem()
    if selected is None: return
    ret = QtGui.QMessageBox.question(self,self.windowTitle(),'Delete '+self.mode+' '+selected,QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel)
    if ret == QtGui.QMessageBox.Cancel: return
    ret = self.manager().delete(selected)
    if ret:
      QtGui.QMessageBox.warning(self,self.windowTitle(),'Error deleting '+self.mode+' '+selected)

  def handleHelp(self):   
    WEBBROWSER().loadWebPage(helpFileName='customisation')



class CCustomListWidget(QtGui.QListWidget):

  def __init__(self,parent):
    QtGui.QListWidget.__init__(self,parent)
    self.connect(self.parent().manager(),QtCore.SIGNAL('listChanged'),self.populate)

  def populate(self):
    self.clear()
    titleList =self.parent().manager().getTitleList()
    for name,title in titleList:
      obj = QtGui.QListWidgetItem(title)
      obj.setData(QtCore.Qt.UserRole,name)
      self.addItem(obj)


  def selectedItem(self):
    seleList = self.selectedItems()
    #print 'contentsTree.selectedItem',seleList
    if len(seleList) == 0:
      return None
    else:
      qvar = seleList[0].data(QtCore.Qt.UserRole)
      #print 'contentsTree.selectedItem',qvar.isNull() , qvar.isValid(),qvar.toString().__str__()
      if qvar.isNull() or (not qvar.isValid()):
        return seleList[0].text().__str__()
      else:
        return qvar.toString().__str__()
    

class CCustomImportDialog(QtGui.QDialog):

  def __init__(self,parent,name=None,fileName=None):
    QtGui.QDialog.__init__(self,parent)
    self.setWindowTitle("Import a "+self.parent().mode)
    self.setLayout(QtGui.QVBoxLayout())
    self.name = name
    self.fileName = fileName
    self.layout().addWidget(QtGui.QLabel('There is already a '+self.parent().mode+' called '+str(name)))
    
    self.bg = QtGui.QButtonGroup(self)
    self.bg.setExclusive(True)
    but =  QtGui.QRadioButton('Overwrite existing '+self.parent().mode,self)
    self.bg.addButton(but,1)
    self.layout().addWidget(but)
    line = QtGui.QHBoxLayout()
    but =  QtGui.QRadioButton('Rename to ',self)
    line.addWidget(but)
    self.rename = QtGui.QLineEdit(self)
    line.addWidget(self.rename)
    self.layout().addLayout(line)
    self.bg.addButton(but,2)
    but.setChecked(True)
    
    butBox = QtGui.QDialogButtonBox(self)
    but = butBox.addButton('Import '+self.parent().mode,QtGui.QDialogButtonBox.ActionRole)
    but.setDefault(False)
    self.connect(but,QtCore.SIGNAL('released()'),self.apply)
    but = butBox.addButton(QtGui.QDialogButtonBox.Cancel)
    self.connect(but,QtCore.SIGNAL('released()'),self.close)
    self.layout().addWidget(butBox)
    
                                                          
  def close(self):
    self.hide()
    self.deleteLater()
    
  def apply(self):
    if self.bg.checkedId() == 2 and len(self.rename.text().__str__())<=0 or self.rename.text().__str__() in self.parent().manager().getList(): return
    self.emit(QtCore.SIGNAL('import'),self.name,self.fileName,2-self.bg.checkedId(),self.rename.text().__str__())
    self.close()

class CCustomCloneDialog(QtGui.QDialog):

  def __init__(self,parent,selected=None):
    QtGui.QDialog.__init__(self,parent)
    self.setWindowTitle("Clone a "+self.parent().mode)
    self.setLayout(QtGui.QVBoxLayout())
    self.label = QtGui.QLabel(self)
    self.layout().addWidget(self.label)
    
    line = QtGui.QHBoxLayout()
    line.addWidget( QtGui.QLabel('Name',self))
    self.nameWidget = QtGui.QLineEdit(self)
    line.addWidget(self.nameWidget)
    self.layout().addLayout(line)

    '''
    line = QtGui.QHBoxLayout()  
    line.addWidget( QtGui.QLabel('Title',self))
    self.titleWidget = QtGui.QLineEdit(self)
    line.addWidget(self.titleWidget)
    self.layout().addLayout(line)

    line = QtGui.QHBoxLayout()
    self.editWidget =  QtGui.QCheckBox('Edit new '+self.parent().mode,self)
    self.editWidget.setChecked(True)
    line.addWidget(self.editWidget )
    self.layout().addLayout(line)
    '''
    
    butBox = QtGui.QDialogButtonBox(self)
    but = butBox.addButton('Clone '+self.parent().mode,QtGui.QDialogButtonBox.ActionRole)
    but.setDefault(False)
    self.connect(but,QtCore.SIGNAL('released()'),self.apply)
    but = butBox.addButton(QtGui.QDialogButtonBox.Cancel)
    self.connect(but,QtCore.SIGNAL('released()'),self.close)
    self.layout().addWidget(butBox)

    self.setSelected(selected)

  def setSelected(self,selected):
    self.selected = selected
    self.label.setText('Clone '+str(selected)+' to new '+self.parent().mode+':')
    '''
    if selected is None:
      self.titleWidget.setText('')
    else:
      self.titleWidget.setText(self.parent().manager().getTitle(selected))
    '''

  def apply(self):
    name = self.nameWidget.text().__str__()
    #title = self.titleWidget.text().__str__()

    if len(name)<=0 or name in self.parent().manager().getList():
      QtGui.QMessageBox.warning(self,'Clone '+self.parent().mode,'Please enter unique name for new '+self.parent().mode)
      return

    '''
    if len(title)<=0 or title == self.parent().manager().getTitle(self.selected):
      QtGui.QMessageBox.warning(self,'Clone '+self.parent().mode,'Please enter a different title')
      return
    '''

    self.emit(QtCore.SIGNAL('clone'),self.selected,name)
    self.close()
