# This file is part of the Coral project.
# Please read the copyright notice in the LICENSE file.

import string
class FieldHandler:
    def __init__(self,codeartifact):
        self.ca=codeartifact

    def makeApply(self,f):
        pass

    def makeFocusOn(self,f):
        pass

    def makeSelect(self,f):
        pass

    def makeNew(self,f):
        pass

    def makeWidget(self,f,xpos,ypos):
        pass
    
class StringFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)

    def makeApply(self,f):
        self.ca.add("t=unicode(self."+unicode(f.widget)+".text())")
        self.ca.add("self.focus."+unicode(f.property)+"=t")
        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
        self.ca.add("")

    def makeFocusOn(self,f):
        self.ca.add("self."+unicode(f.widget)+".setText(unicode(element."+unicode(f.property)+"))")
        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
        self.ca.add("")

    def makeWidget(self,f,xpos,ypos):
        w=200
        h=20
        self.ca.add('self.'+unicode(f.widget)+'=QLineEdit(self,"'+unicode(f.widget)+'")')
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')

        return w,h

class TextFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)

    def makeApply(self,f):        
        self.ca.add("t=unicode(self."+unicode(f.widget)+".text())")
        self.ca.add("self.focus."+unicode(f.property)+"=t")
        self.ca.add("")

    def makeFocusOn(self,f):
        self.ca.add("line,index=self."+unicode(f.widget)+".getCursorPosition()")
        self.ca.add("self."+unicode(f.widget)+".setText(unicode(element."+unicode(f.property)+"))")
        self.ca.add("self."+unicode(f.widget)+".setCursorPosition(line,index)")
        self.ca.add("")

    def makeWidget(self,f,xpos,ypos):
        self.ca.add('self.'+unicode(f.widget)+'=QTextEdit(self,"'+unicode(f.widget)+'")')
        h=200
        w=300
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')

        return w,h

class EnumerationFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)

    def makeApply(self,f):
        self.ca.add("self.focus."+unicode(f.property)+"=self."+unicode(f.widget)+".currentItem()")
        self.ca.add("")

    def makeFocusOn(self,f):
        self.ca.add("self."+unicode(f.widget)+".clear()")
        self.ca.add('property = element.__type__().getPropertyByName("'+unicode(f.property)+'")')
        self.ca.add("ed = property.getTarget()")
        self.ca.add("size = ed.size()")
        self.ca.add("for i in xrange(size):")
        self.ca.indent(1)
        self.ca.add('self.'+unicode(f.widget)+'.insertItem(ed.getDescription(i))')
        self.ca.indent(-1)
        self.ca.add("self."+unicode(f.widget)+".setCurrentItem(element."+unicode(f.property)+".__getEValue__())")

        self.ca.add("")
        
    def makeWidget(self,f,xpos,ypos):
        w=200
        h=20
        self.ca.add('self.'+unicode(f.widget)+'=QComboBox(0,self,"'+unicode(f.widget)+'")')
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')

        return w,h

class BooleanFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)

    def makeApply(self,f):
        self.ca.add("self.focus."+unicode(f.property)+"=self."+unicode(f.widget)+".isChecked()")
        self.ca.add("")

    def makeFocusOn(self,f):
        self.ca.add("self."+unicode(f.widget)+".setChecked(element."+unicode(f.property)+")")
        self.ca.add("")
       
    def makeWidget(self,f,xpos,ypos):
        w=200
        h=20
        self.ca.add('self.'+unicode(f.widget)+'=QCheckBox(self,"'+unicode(f.widget)+'")')
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')
        self.ca.add('self.'+unicode(f.widget)+'.setText("'+unicode(f.property)+'")')

        return w,h

class IntegerFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)

    def makeApply(self,f):
        self.ca.add("t=unicode(self."+unicode(f.widget)+".text())")
        self.ca.add("if not t or not t.isdigit():")
        self.ca.indent(1)
        self.ca.add('print "the value ",t," has to be an integer value"')
        self.ca.indent(-1)
        self.ca.add("else:")
        self.ca.indent(1)
        self.ca.add("self.focus."+unicode(f.property)+"=int(t)")
        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
        self.ca.indent(-1)
        self.ca.add("")

    def makeFocusOn(self,f):
        self.ca.add("self."+unicode(f.widget)+".setText(unicode(element."+unicode(f.property)+"))")
        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
        self.ca.add("")
        
    def makeWidget(self,f,xpos,ypos):
        w=200
        h=20
        self.ca.add('self.'+unicode(f.widget)+'=QLineEdit(self,"'+unicode(f.widget)+'")')
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')

        return w,h
    
class ReferenceFieldHandler(FieldHandler):
    def __init__(self,codeartifact):
        FieldHandler.__init__(self,codeartifact)


    def makeApply(self,f):
##        self.ca.add("if not self."+unicode(f.widget)+".edited():")
##        self.ca.indent(1)
##        self.ca.add("return")
##        self.ca.indent(-1)
##        self.ca.add("t=unicode(self."+unicode(f.widget)+".text())")
##        self.ca.add("root=self.focus.__getRoot__()")
##        self.ca.add('ed=self.focus.__type__().getPropertyByName("'+unicode(f.property)+'").getTarget()')
##        self.ca.add("for e in root.__getAllParts__():")
##        self.ca.indent(1)
##        self.ca.add("if e.oclIsKindOf(ed) and getFQName(e,1)==t:")
##        self.ca.indent(1)
##        self.ca.add("self.focus."+unicode(f.property)+"=e")
##        self.ca.indent(-2)
##        self.ca.add('if t!="" and self.focus.'+unicode(f.property)+':')
##        self.ca.indent(1)
##        self.ca.add("self.focus."+unicode(f.property)+".name=t")
##        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
##        self.ca.indent(-1)
        self.ca.add("")


    def makeFocusOn(self,f):
        self.ca.add('self.'+unicode(f.widget)+'.setText("")')
        self.ca.add("if element."+unicode(f.property)+":")
        self.ca.indent(1)
        self.ca.add("self."+unicode(f.widget)+".setText(getFQName(element."+unicode(f.property)+",1))")
        self.ca.add("self."+unicode(f.widget)+".setEdited(0)")
        self.ca.indent(-1)
        self.ca.add("")
        
    def makeSelect(self,f):
        self.ca.indent(1) 
        self.ca.add("def "+unicode(f.selectwidget)+"Clicked(self):") 
        self.ca.indent(1)
        self.ca.add('ed=self.focus.__type__().getPropertyByName("'+f.property+'").getTarget()')
        self.ca.add("r=ElementPick().pick(self.focus, ed)")
        self.ca.add("if not r:")
        self.ca.indent(1)
        self.ca.add("return")
        self.ca.indent(-1)
        self.ca.add("coral.getTransactionManager().beginModifyCmd()")
        self.ca.add("try:")
        self.ca.indent(1)
        self.ca.add("self.focus."+unicode(f.property)+"=r")
        self.ca.add("self."+unicode(f.widget)+".setText(getFQName(r,1))")
        self.ca.indent(-1)
        self.ca.add("finally:")
        self.ca.indent(1)
        self.ca.add("coral.getTransactionManager().endModifyCmd()")
        self.ca.add("")
        self.ca.resetIndent()

    def makeNew(self,f):
        self.ca.indent(1)
        self.ca.add("def "+unicode(f.newwidget)+"Clicked(self):")
        self.ca.indent(1)
        self.ca.add("coral.getTransactionManager().beginModifyCmd()")
        self.ca.add("try:")
        self.ca.indent(1)
        newFlag=False
        if f.newElement:
            ne=""
            for i in f.newElement:
                if string.strip(str(i)):
                    ne += i
            if ne != "":
                newFlag=True
        if f.newElement and newFlag:
            for s in f.newElement:
                self.ca.add(unicode(s))
        else:
            self.ca.add('prop=self.focus.__type__().getPropertyByName("'+f.property+'")')
            self.ca.add("asslist=AssociationListE(self.parent(),prop,self.focus,self.manager)")
            self.ca.add("asslist.show()")
        self.ca.resetIndent()
        self.ca.indent(2)
        self.ca.add("finally:")
        self.ca.indent(1)
        self.ca.add("coral.getTransactionManager().endModifyCmd()")
        self.ca.add("")
        self.ca.resetIndent()
                    
                   
        # BUG does not work, abd is not metamodel-independent
##        self.ca.indent(1) 
##        self.ca.add("def "+unicode(f.newwidget)+"Clicked(self):") 
##        self.ca.indent(1)
##        self.ca.add("coral.getTransactionManager().beginModifyCmd()")
##        self.ca.add("try:")
##        self.ca.indent(1)
##        self.ca.add('ed=self.focus.__type__().getPropertyByName("'+f.property+'").getTarget()')
##        self.ca.add("new=elementFactory(ed)")
##        self.ca.add('if new and self.focus:')
##        self.ca.indent(1)
##        self.ca.add("root=self.focus.__getRoot__()")
##        self.ca.add("root.ownedElement.insert(new)")
##        self.ca.add("self.focus."+unicode(f.property)+"=new")
##        self.ca.add("self."+unicode(f.widget)+".setText(unicode(new.name))")
##        self.ca.indent(-2)
##        self.ca.add("finally:")
##        self.ca.indent(1)
##        self.ca.add("coral.getTransactionManager().endModifyCmd()")
##        self.ca.add("")
##        self.ca.resetIndent()


    def makeDoubleClicked(self,f):
        self.ca.indent(1)
        self.ca.add("def doubleClicked(self):")
        self.ca.indent(1)
        self.ca.add('from coral.modeler import action')
        self.ca.add('if self.fieldTarget:')
        self.ca.indent(1)
        self.ca.add('for e in action.getCurrentHandler("modeler").editorSet.getEditors():')
        self.ca.indent(1)
        self.ca.add('if isinstance(e,coral.modeler.outline.outlineeditor.OutlineEditor):')
        self.ca.indent(1)
        self.ca.add('e.focusOn(self.fieldTarget)')
        self.ca.add('e.notifyFocusOn(self.fieldTarget)')
        self.ca.add('break')
        self.ca.indent(-5)
        self.ca.add("")

    def makeWidget(self,f,xpos,ypos):

        w=200
        h=20

        self.ca.add('from coral.modeler.property.propertyeditor import ReferenceLineEdit')
        self.ca.add('self.'+unicode(f.widget)+'=ReferenceLineEdit(self,"'+unicode(f.widget)+'")')
        self.ca.add('self.'+unicode(f.widget)+'.setGeometry(QRect('+unicode(xpos)+
                           ','+unicode(ypos)+','+unicode(w)+','+unicode(h)+'))')

        w=28
        delta = 210

        self.ca.add('noselect = False')
        self.ca.add('self.'+unicode(f.newwidget)+'=QToolButton(self,"'+unicode(f.newwidget)+'")')
        self.ca.add('self.'+unicode(f.newwidget)+'.setGeometry(QRect('+unicode(xpos+delta)+
                    ','+unicode(ypos-5)+','+unicode(w)+',28))')
        self.ca.add('self.'+unicode(f.newwidget)+'.setPixmap(iconcache.getIcon("newAction"))')
        self.ca.add('self.'+unicode(f.newwidget)+'.setTextLabel("New Element")')

        # If there is no code in 'newElement', we hide the 'New Element' button
        empty = True
        for line in f.newElement:
            if unicode(line).strip():
                empty = False
                break
        ## This is a bit dirty. If there is no code-snippet and the property is a composition
        ## we should show the button. Bad thing: has to be done at run time.
        ## We may have a  problem if aggregation-kind is changed in an overridden property (TLU)
        if empty and len(f.editor.canedit) == 1:
            self.ca.add('association = False')
            self.ca.add('for mc in '+unicode(f.editor.canedit[0])+':')
            self.ca.indent(1)
            self.ca.add('if mc.getPropertyByName(\"'+unicode(f.property)+'\") and mc.getPropertyByName(\"'+unicode(f.property)+'\").isAssociation():')
            self.ca.indent(1)
            self.ca.add('association = True')
            self.ca.add('self.'+unicode(f.newwidget)+'.setHidden(True)')
            self.ca.add('noselect = True')
            self.ca.add('break')
            self.ca.indent(-2)

        delta += 40
            
        self.ca.add('self.'+unicode(f.selectwidget)+'=QToolButton(self,"'+unicode(f.selectwidget)+'")')
        self.ca.add('if noselect:')
        self.ca.indent(1)
        self.ca.add('self.'+unicode(f.selectwidget)+'.setGeometry(QRect('+unicode(xpos+delta-40)+
                           ','+unicode(ypos-5)+','+unicode(w)+',28))')
        self.ca.indent(-1)
        self.ca.add('else:')
        self.ca.indent(1)
        self.ca.add('self.'+unicode(f.selectwidget)+'.setGeometry(QRect('+unicode(xpos+delta)+
                           ','+unicode(ypos-5)+','+unicode(w)+',28))')
        self.ca.indent(-1)
        self.ca.add('self.'+unicode(f.selectwidget)+'.setPixmap(iconcache.getIcon("linkAction"))')
        self.ca.add('self.'+unicode(f.selectwidget)+'.setTextLabel("Select Element")')
        
        # Don't mess up width, this should be delta + 20
        # but it may affect columns and stuff, so it's left unchanged
        return 270,h
