"""
     qtgui/pictureWizardGui.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2011 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.
"""
import copy
from PyQt4 import QtGui,QtCore
from global_definitions import *
import MGSimpleDialog,mgWidgets
import os


#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class drawingStyleGui(QtGui.QWidget):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------

  def __init__(self,parent=None,height=100,description=0,disable_query_scenes=False):
    QtGui.QWidget.__init__(self,parent)
    self.disable_query_scenes = disable_query_scenes
    self.picSize = height
    self.draw(description=description)
    self.show()

#----------------------------------------------------------------------
  def draw(self,description=0):
#----------------------------------------------------------------------
    description_height = 80
    layout = QtGui.QHBoxLayout()
    margin = 0
    layout.setContentsMargins(margin,margin,margin,margin)
    layout.setSpacing(margin)
    #self.setFixedHeight(self.picSize+(2*margin)+(description*description_height))

    # tree widget to select drawing mode
    self.tree = self.drawTree()
    #self.tree.setFixedWidth(250)
    self.setStyle()
    layout.addWidget(self.tree)

    self.connect(self.tree,QtCore.SIGNAL('itemSelectionChanged()'),self.changePicture)
    self.connect(self.tree,QtCore.SIGNAL('itemEntered(QTreeWidgetItem*,int)'),self.changePicture)
    self.connect(self.tree,QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*,int)'),self.handleDoubleClick)
    #layout2.addWidget(self.wizard_radio,0)
    self.wiz_label = QtGui.QLabel()
    wiz_pixmap = QtGui.QPixmap("ccp4mg_icon.png")
    self.wiz_label.setPixmap(wiz_pixmap)
    layout.addWidget(self.wiz_label)

    if description:
      self.descriptionWidget = QtGui.QTextEdit(self)
      self.descriptionWidget.setReadOnly(1)
      self.descriptionWidget.setFixedHeight(description_height)

      layout0 = QtGui.QVBoxLayout()
      layout0.addLayout(layout)
      layout0.addWidget(self.descriptionWidget)
      self.setLayout(layout0)
    else:
      self.descriptionWidget = None   
      layout.addStretch()
      self.setLayout(layout)

    self.setStyle()
    self.changePicture()
    

#----------------------------------------------------------------------
  def drawTree(self):
#----------------------------------------------------------------------
    import string
    picwiz = PICTUREWIZARD()
    menu_list = picwiz.define_model_style_menu(style=[])
    #print menu_list
    
    tree = QtGui.QTreeWidget()
    tree.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
    tree.setToolTip('Select a drawing style to apply to a model')

    for group in menu_list:
      #print "group",group
      item = QtGui.QTreeWidgetItem([string.replace(group[0],'_',' ')])
      item.setFlags(QtCore.Qt.ItemIsEnabled)
      tree.addTopLevelItem(item)
      for file,query in group[1]:
        if query and self.disable_query_scenes:
          item0 = QtGui.QTreeWidgetItem([string.replace(file,'_',' ')])
          if item0:
            item0.setFlags(QtCore.Qt.NoItemFlags)
            item.addChild(item0)
        else:
          item0 = QtGui.QTreeWidgetItem([string.replace(file,'_',' ')])
          if item0:
            item0.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEnabled)
            item.addChild(item0)
    #tree.headerItem().setText(0,'Representation style')
    tree.headerItem().setHidden(1)
    return tree

#----------------------------------------------------------------------
  def setStyle(self,style=''):
#----------------------------------------------------------------------
    #print "pictureWizardGui setStyle",style
    import string
    if style:
      import types
      if not isinstance(style,types.ListType):
        style = string.split(string.replace(style,'_',' '),':')
      self.style = style
    else:
      self.style = string.split(
        string.replace( PICTUREWIZARD().default_drawing_style,'_',' '),':')
    #print "setSelection", selection
    items = self.tree.findItems(QtCore.QString(self.style[0]),QtCore.Qt.MatchExactly)
    # Surely there is  method to search a branch for specific text label???
    # But I can figure what is is so try this ..
    #print "drawingStyleGui setStyle items",self.style,items
    hit = -1
    ii = 0
    while hit<0 and ii<len(items):
      nChildren = items[ii].childCount()
      nc = 0
      while hit<0 and nc<nChildren:
        #print "drawingStyleGui.setStyle testing",str(items[ii].child(nc).text(0))
        if str(items[ii].child(nc).text(0)) == self.style[1]:
          hit = nc
          self.tree.setCurrentItem(items[ii].child(nc))
        nc = nc + 1
      ii = ii +1
   
#----------------------------------------------------------------------
  def changePicture(self):
#----------------------------------------------------------------------
    import string,os
    current = self.tree.currentItem()
    #print "changePicture current",current
    if current:
      if not current.parent():
        self.setStyle(self.style)
      else:
        #self.currentItem = current
        subdir = string.replace(str(current.parent().text(0)),' ','_')
        style = string.replace(str(current.text(0)),' ','_')
        self.style = [subdir,style]
        style_file = PICTUREWIZARD().snapshot_file(drawing_style=subdir+':'+style,mode='pngsnapshot')
        #print "changePicture ",subdir,style,style_file       
        try:
          wiz_pixmap = QtGui.QPixmap(style_file)
          wiz_pixmap = wiz_pixmap.scaledToHeight(self.picSize,QtCore.Qt.SmoothTransformation)
          self.wiz_label.setPixmap(wiz_pixmap)
        except:
          print "No",style_file
          
        pic_file = PICTUREWIZARD().snapshot_file(drawing_style=subdir+':'+style,mode='mgpic')
        rv,title = PICTUREWIZARD().read_mgpic_file_section(filename=pic_file,section ='TITLE')
        desc_text = ''
        if not rv:
          self.wiz_label.setToolTip(title)
          desc_text = '<b>'+title+'</b><br/>'
        
        if self.descriptionWidget:
          self.descriptionWidget.clear()
          rv,desc = PICTUREWIZARD().read_mgpic_file_section(filename=pic_file,section ='NOTES')
          #print 'changePicture rv,desc',rv,desc
          if not rv: self.descriptionWidget.setText(desc_text+desc.replace('\n','<br>'))
              
        PICTUREWIZARD().set_default_drawing_style(subdir+':'+style)
        self.emit(QtCore.SIGNAL('changed'))

#----------------------------------------------------------------------
  def getStyle(self):
#----------------------------------------------------------------------
    import string
    current =  self.tree.currentItem()
    #print 'getStyle',current, current.parent(),current.text(0)
    if current and current.parent(): 
      subdir = string.replace(str(current.parent().text(0)),' ','_')
      style = string.replace(str(current.text(0)),' ','_')
      return subdir+':'+style
    else:
      return ''

  def handleDoubleClick(self,item,col):
    print "handleDoubleClick",item,col


  def handleItemEntered(self,item,col):
    print "handleItemEntered",item,col

    
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class drawingStyleCombo(QtGui.QComboBox):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------

  def __init__(self,parent=None,style=[]):
    super(drawingStyleCombo,self).__init__(parent)
    self.setEditable(0)
    self.setMaxVisibleItems(10)
    self.populateMenu(style=style)

#----------------------------------------------------------------------
  def populateMenu(self,style=[]):
#----------------------------------------------------------------------

    picwiz = PICTUREWIZARD()

    menu_list,alias_list = picwiz.define_model_style_menu(style=style)
    
    for ii in range(0,len(menu_list)):
      self.addItem(menu_list[ii],QtCore.QVariant(alias_list[ii]))

    if alias_list.count(picwiz.default_drawing_style):
      self.setCurrentIndex(alias_list.index(picwiz.default_drawing_style))
    
  def getStyle(self):
    alias = str(self.itemData(self.currentIndex()).toString())
    PICTUREWIZARD().default_drawing_style=alias
    return alias


#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class pictureWizardGui(QtGui.QDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
    
#-------------------------------------------------------------------
  def __init__(self,parent=None,drawing_style='',moldata_name='',recentreIfOnlyOne=False):
#-------------------------------------------------------------------
    QtGui.QDialog.__init__(self,parent)
    #self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    self.recentreIfOnlyOne = recentreIfOnlyOne
    self.drawing_style = ''
    self.choices = []
    self.moldata_name = moldata_name
    if moldata_name=='ALL':
      self.draw(disable_query_scenes=1)
      self.setWindowTitle('Picture wizard to apply to ALL VISIBLE models')
    else:
      self.draw()
      self.setWindowTitle('Picture wizard: '+moldata_name)
    self.drawingStyleWidget.setStyle(drawing_style)
    self.updateDrawingStyle(drawing_style)

    self.connect(self.drawingStyleWidget,QtCore.SIGNAL('changed'),self.updateDrawingStyle)

    self.show()
      
#-------------------------------------------------------------------
  def draw(self,disable_query_scenes=0):
#-------------------------------------------------------------------
    layout = QtGui.QVBoxLayout()

    self.deleteWidget = QtGui.QCheckBox('Delete any existing display object',self)
    self.deleteWidget.setChecked(1-PICTUREWIZARD().keep_display_objects)
    layout.addWidget(self.deleteWidget)

    self.drawingStyleWidget = drawingStyleGui(self,description=1,height=150,disable_query_scenes=disable_query_scenes)
    layout.addWidget(self.drawingStyleWidget)

    self.definitionFrame = QtGui.QFrame(self)
    layout.addWidget(self.definitionFrame)

    button_box = QtGui.QDialogButtonBox(self)
    button_box.setOrientation(QtCore.Qt.Horizontal)
    for label,role,slot in [['Create picture',QtGui.QDialogButtonBox.ActionRole,self.Apply],
                 ['Cancel',QtGui.QDialogButtonBox.RejectRole,self.hide],
                 ['Help',QtGui.QDialogButtonBox.HelpRole,self.Help]]:
      button = button_box.addButton(label,role)
      button.setAutoDefault(0)
      self.connect(button,QtCore.SIGNAL('clicked()'),slot)
    layout.addWidget(button_box)
    self.setLayout(layout)

#-------------------------------------------------------------------
  def updateDrawingStyle(self,drawing_style=''):
#-------------------------------------------------------------------
    if not drawing_style: drawing_style = self.drawingStyleWidget.getStyle()
    #print 'pictureWizardGui.updateDrawingStyle',drawing_style
    if drawing_style == self.drawing_style: return
    self.drawing_style = drawing_style
    self.filename = PICTUREWIZARD().snapshot_file(drawing_style=self.drawing_style,mode='mgpic')
    #rv,title = PICTUREWIZARD().read_mgpic_file_section(filename=self.filename,section ='TITLE')

    rv=PICTUREWIZARD().read_mgpic_file_choices(drawing_style=drawing_style)
    #print 'read_mgpic_file_choices',rv
    if rv[0]>0:
      QtGui.QMessageBox.warning(self,'Error reading drawing style '+drawing_style,rv[1])
    else:
      self.choices = rv[1]
    
    #if self.moldata_name!='ALL': self.drawDefinitionFrame()
    self.drawDefinitionFrame()
    

#-------------------------------------------------------------------
  def drawDefinitionFrame(self):
#-------------------------------------------------------------------
    togo = self.definitionFrame.findChildren(QtGui.QWidget)
    params = self.getParams()
    #print "drawDefinitionFrame togo",togo,self.choices
    for item in togo: item.close()

    layout = self.definitionFrame.layout()
    if layout is None:
      layout = QtGui.QGridLayout()
      layout.setSpacing(0)
      layout.setContentsMargins(1,1,1,1)
      self.definitionFrame.setLayout(layout)

    if self.moldata_name=='ALL': 
      dataobjs = get_dataobj(object_type='MolData')
      firstChains = None
      allChains = []
      for o in dataobjs:
            if hasattr(o,"chains") and firstChains == None:
              firstChains = copy.deepcopy(o.chains)
              allChains = copy.deepcopy(o.chains)
            if hasattr(o,"chains") and firstChains != None:
              for ch in allChains[:]:
                if not ch in o.chains:
                   allChains.remove(ch)
      allChains.insert(0,"")
      nn = -1
      for defn in self.choices:
        defn_type = defn.get('type','')
        if ['chain'].count(defn_type):
          nn = nn + 1
          label = QtGui.QLabel(defn.get('label',''),self)
          layout.addWidget(label,nn,0,1,1)
          name = defn.get('name','')        
          if defn_type == 'chain':
            widget = QtGui.QComboBox(self)
            widget.addItems(allChains)
          widget.setObjectName(name)
          widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
          layout.addWidget(widget,nn,1,1,1)
    else:
      nn = -1
      for defn in self.choices:
        defn_type = defn.get('type','')
        if ['chain','monomer'].count(defn_type):
          nn = nn + 1
          label = QtGui.QLabel(defn.get('label',''),self)
          layout.addWidget(label,nn,0,1,1)
          name = defn.get('name','')        
          if defn_type == 'chain':
            #modelGroups = ['peptide','nucleic','monomers']
            widget=mgWidgets.mgAtomPicker(self,MolData_name=self.moldata_name,mode='range',blank=1)
            if params.has_key(name): widget.setSelection(atomName=params[name])
          elif defn_type == 'monomer':
            modelGroups = ['monomers','saccharide','solute','peptide','nucleic']
            widget = mgWidgets.mgSelectionCombo(self,abstractModel=data(self.moldata_name).treeModel,modelGroups=modelGroups,selectionWidgets=['namedSelection','chains'])
            if params.has_key(name): widget.setText(params[name])
          widget.setObjectName(name)
          widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
          layout.addWidget(widget,nn,1,1,1)
         
        elif defn_type == 'logical':
          nn = nn + 1
          widget = QtGui.QCheckBox(defn.get('label',''),self)
          name = defn.get('name','')
          widget.setObjectName(name)
          if params.has_key(name): widget.setChecked(params[name])
          widget.setChecked(int(defn.get('initial',0)))
          widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
          layout.addWidget(widget,nn,0,1,2)
        else:
          pass
          #print 'drawDefinitionFrame undrawn',defn
        
#-------------------------------------------------------------------
  def Apply(self):
#-------------------------------------------------------------------
    self.hide()
    if self.moldata_name == 'ALL':
      target_list = get_dataobj(object_type='MolData')
      force_recolour_bymol = True
    else:
      target_list = [data(name=self.moldata_name)]
      force_recolour_bymol = False
    for target in target_list:
      if target.visible:
        target.applyDrawingStyle(drawing_style=self.drawingStyleWidget.getStyle(),
                             chosen=self.getParams(),
                             keep_display_objects=1-int(self.deleteWidget.isChecked()),force_recolour_bymol=force_recolour_bymol)

    import rebuild
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

    # Draw the new display objects on the display table
    dt = DISPLAYTABLE()
    if dt: dt.emit(QtCore.SIGNAL("applyWizard"))
    for target in target_list:
      obj = DISPLAYTABLE().getDataObj(target.name)
      if obj: obj.updateDispObj()
    if dt: dt.emit(QtCore.SIGNAL("finishedApplyWizard"))

    if self.recentreIfOnlyOne and len(get_dataobj(object_type='MolData')) == 1:
      MAINWINDOW().handleRecentre(glide=0)
    self.close()


#-------------------------------------------------------------------
  def undo(self):
#-------------------------------------------------------------------
    pass

    
#-------------------------------------------------------------------
  def getParams(self):
#-------------------------------------------------------------------
    pars = {}
    for defn in self.choices:
      widget = self.definitionFrame.findChild(QtGui.QWidget,defn.get('name',''))
      if widget:
        if ['monomer'].count(defn.get('type','')):
          pars[defn['name']] = str(widget.text())
        if ['chain'].count(defn.get('type','')) and hasattr(widget,"selection"):
          pars[defn['name']] = str(widget.selection())
        elif ['chain'].count(defn.get('type','')) and hasattr(widget,"currentText") and widget.currentText() != "":
          ch = str(widget.currentText())
          if not ch.endswith('/'):
            ch = ch + '/'
          pars[defn['name']] = ch
        elif  ['logical'].count(defn.get('type','')):
          pars[defn['name']] = int(widget.isChecked())
    #print 'getParams',pars
    return pars


  def Help(self):
    HELPBROWSER().loadMgHelp(file='picture_wizard.html')
