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

LABEL_STYLE_PARAM = ['mol_number','mol_name','model_id', \
                              'chain_id','sequence', \
                              'residue_type','atom_id', \
                              'element','energy_type','xyz', \
                              'bval','occ','charge','symid','symop']
LABEL_STYLE_ALIAS = ['Molecule number','Molecule name', \
                              'Model id','Chain id','Residue id', \
                              'Residue type','Atom name', \
                              'Element','Energy type','Coordinates', \
                              'Temperature factor','Occupancy','Charge',
                              'Sym id','Sym operation']
LABEL_STYLE_GUI_ORDER = [ 0,1,13,14,2,3,4,5,6,7,8,9,10,11,12]

LABEL_SELECTION_MENU =  ['no atoms','one atom/residue',
         'one atom/5 residues','one atom/10 residues','SSE termini',
         'chain termini', 'NMR/symmetry model', 'all atoms']
LABEL_SELECTION_ALIAS = ['label_no','label_one_atom_1','label_one_atom_5',
           'label_one_atom_10','label_SSEtermini','label_termini','label_modeltermini','label_all']

LABEL_STYLE_MASK = [ [],[],[1],[2],[3,4],[5],[6,7],[8],[10],[11],[13],[15],[17],[],[]]
DEFAULT_LABEL_STYLE = [0,0,0,1,1,1,1,0,0,0,0,0,0,0,0]

#    Label atom Mask parameters - see mmut/mman_manager.h
# 0  Molecule
# 1  Model
# 2  Chain Id
# 3  Sequence number
# 4  Insertion code
# 5  Residue name
# 6  Atom id
# 7  Alternate position
# 8  Element
# 9  Index
# 10 Atom energy type
# 11 xyz
# 12 Sig x,y,z 
# 13 Bval
# 14 Sig bval
# 15 occ
# 16 Sig occ
# 17 charge
# 18 Secondary structure 


#------------------------------------------------------------------------
#------------------------------------------------------------------------
#------------------------------------------------------------------------

class MolLabel(dataobj.Dependency):

  class_dependents = {}
  
  initialisation = {
    'label_user_oneperres' : 1,
    'label_user_selparams' : {},
    'label_colour' : 'complement' }
  initialisation_order = ['label_select','label_style','label_colour','label_user_selparams','label_user_oneperres','truncate_mol_name_length','truncate_mol_name']
  
  def __init__(self,parent='',mol='',visibility='1',name='', \
                                    params={},**keywords):

    #print 'MolLabel.init params',params
    self.object_type = 'MolLabel'
    self.mol = get_dataobj(name=mol)[0]
    self.parent = get_dispobj(name=parent)
    self.do_redraw = 1

    PM('atom_label_params').add_dependent(handleAtomLabelParamsManager)
        
    # Initialise
    pars = PM('atom_label_params').getparams()
    pars.update(params)
    pars.update(keywords)
    for item in ['label_style','label_select','truncate_mol_name','truncate_mol_name_length']:
      setattr(self,item,pars.get(item))
    for key,value in MolLabel.initialisation.items():
      setattr(self,key,value)
    
    
    # Beware if reading pre2.0 status will have name without 'label_'
    for key in MolLabel.initialisation_order:
      if params.has_key(key[6:]):
        params[key] = params[key[6:]]
        del params[key[6:]]
    # Handle change in label_alias needed to avoid clashing action
    # names (e.g. 'all') in  Qt gui for GDispObj
    if params.has_key('label_select'):
      if params['label_select'][0:5] != 'label':
        params['label_select'] = 'label_'+params['label_select']
        
    self.setparams(params)
        
    # Beware extended options - possible issues in restoring status
    diflen = len(LABEL_STYLE_ALIAS)-len(self.label_style)
    if diflen>0:
      for i in range(0,diflen): self.label_style.append(0)
      
    dataobj.Dependency.__init__(self)
    self.update_dependents('create')

  def set_selection(self,label_select='',label_user_oneperres=0):
    self.label_select = label_select
    
  def set_style(self,label_style=''):
    self.label_style = label_style

#----------------------------------------------------------------------
  def setparams(self,params={},force=0,**kw):
#----------------------------------------------------------------------
    params.update(kw)
    #print "MolLabel.setparams",params
    for item in ['label_style','label_select','truncate_mol_name','truncate_mol_name_length']:
      if params.has_key(item) and params.get(item) != getattr(self,item):
        self.do_redraw = 2
        setattr(self,item,params.get(item))

    if force: self.do_redraw = 2
    # beware - we are not handling user seelction!!!
      
#------------------------------------------------------------------------
  def params(self,all=1):
#------------------------------------------------------------------------
    pars = {}
    #if self.select == 'label_no': return pars

    if all:
      for key in MolLabel.initialisation_order:
        pars[key] = getattr(self,key,'')
    else: 
      for key in MolLabel.initialisation_order[0:3]:
        pars[key] = getattr(self,key,'')
      for key in MolLabel.initialisation_order[3:]:
        value = getattr(self,key,'')
        if value != MolLabel.initialisation[key]: pars[key] = value
    return pars


#------------------------------------------------------------------
  def update_data_status(self,new_params):
#------------------------------------------------------------------
    import utils
    rv = 0
    diffs = utils.dict_diffs(self.params(),new_params)[1]
    #print "MolLabel update_data_status diffs",diffs
    if diffs.has_key('label_user_selparams'):
      rv = 1
      self.user_selparams = diffs['label_user_selparams']
      self.handle_user_selection()
    if diffs.has_key('label_user_oneperres') or diffs.has_key('label_select'):
      rv = 1
      self.set_selection(label_user_oneperres=diffs.get('label_user_oneperres',''), \
                         label_select=diffs.get('label_select',''))
    if diffs.has_key('label_style'):
      rv = 1
      self.set_style(label_style = diffs['label_style'])

    if rv: self.set_do_redraw()
    return rv
      
#----------------------------------------------------------------------
  def set_do_redraw(self,mode=2):
#----------------------------------------------------------------------
    self.do_redraw = mode
    
  
#------------------------------------------------------------------
  def handle_moving_data(self,attribute='',master='',**keywords):
#------------------------------------------------------------------
    self.do_redraw = 2
    
#------------------------------------------------------------------
  def draw (self ):
#------------------------------------------------------------------
    #print "MolLabel draw",self.do_redraw,self.label_select
    if self.do_redraw == 0:
      return 0
    elif self.label_select == 'label_no':
      self.delete_labels()
      return 0
    else:
      # Treat all cases the same
      self.delete_labels()
      self.create_labels()
      self.do_redraw = 0
      return 1
  
#-----------------------------------------------------------------
  def create_labels(self):
#------------------------------------------------------------------

    import sys
    #print "create_labels label_select",self.parent,self.label_select
    if self.label_select == 'label_no':
      return

    SelHandle = model_selection.SelHandle(self.mol.name)
    SelHandle.mergeSelection(op='new',SelHandle=self.parent.SelHandle)

    period = 1
    if self.label_select[6:] == 'all':
      pass
    elif [ 'termini','SSEtermini','modeltermini'].count(self.label_select[6:]):
      SelHandle.mergeSelection(self.label_select[6:],'and')
      
    elif self.label_select[6:14] == 'one_atom':
      SelHandle.mergeSelection('one_atom','and')
      period = int(self.label_select[15:])
      
    #print "create_labels nAtoms",SelHandle.getNofAtoms()
    # Convert the GUI selection mask to the mask for the AtomLabel methd
    import pygl_coord
    mask = pygl_coord.inta(20)
    for i in range(0,20): mask[i] = 0
    for i in range(0,len(self.label_style)):
      if self.label_style[i]:
        for j in LABEL_STYLE_MASK[i]: mask[j] = 1
    moln = ''


    if self.label_style[0]:
      moln = str(self.mol.MolData_number)+')'
    if self.label_style[1]:
      if self.truncate_mol_name:
        #print "name_label",self.mol.name_label
        moln = moln+self.mol.name_label[0:min(self.truncate_mol_name_length,len(self.mol.name_label))]+':'
      else:
        moln = moln+self.mol.name_label+':'

        
    import global_definitions
    glWidgets = global_definitions.GLWIDGETS()
    if glWidgets and len(glWidgets)>0 and hasattr(glWidgets[0],"getBackground"):
      red,green,blue = glWidgets[0].getBackground()
    if sys.argv.count('-quit'):
      self.parent.CMgAppUtils.CreateAtomLabels(SelHandle.getSelHnd(),self.parent.label_graphmod.obj,mask,period,moln,1-red/255.,1-green/255.,1-blue/255.)
    else:
      self.parent.CMgAppUtils.CreateAtomLabels(SelHandle.getSelHnd(),self.parent.label_graphmod.obj,mask,period,moln)
    font =  FONTMANAGER().getFont('atom_label')
    #print "MolLabel font",font; sys.stdout.flush()
    self.parent.label_graphmod.obj.SetTextFont( str(font['family']), str(font['weight']), \
                                     str(font['slant']),int(font['size']),int(font['underline']))
    self.parent.label_graphmod.obj.rebuild()
    del  SelHandle

#-----------------------------------------------------------------------
  def delete_labels (self) :
#-----------------------------------------------------------------------
    # Delete all of the text graphical objects associated with all of the
    # molecule dispobj
    if not self.parent.label_graphmod: return
    self.parent.CMgAppUtils.DeleteAtomLabels(self.parent.label_graphmod.obj)   
    #self.parent.label_graphmod.obj.rebuild()


#-----------------------------------------------------------------------
def atomLabelParamsManager(name='atom_label_params',copy_from=None):
#-----------------------------------------------------------------------
  import services
  pm = services.ParamsManager( name=name,
              title='Atom label options',
              copy_from = copy_from,              
              picture_definition = 1,
              gui=['label_select','label_style','truncate_mol_name_length','truncate_mol_name','show_number_label' ],
              default = { 
                        'label_select': 'label_no',
                        'label_style': [0,0,0,1,1,1,1,0,0,0,0,0,0],
                        'truncate_mol_name_length': 6,
                        'truncate_mol_name': 0,
                        'show_number_label' : 0 },
              help = '')
  return pm


#-------------------------------------------------------------------
def handleAtomLabelParamsManager( **kw ):
#-------------------------------------------------------------------
    # Get list of model display objects which may need updating
    params = PM('atom_label_params').getparams()
    obj_list = get_dispobj(object_type='MolDisp')
        
    for obj in obj_list:
      obj.label.setparams(params)


