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

from coral.modeler.extension import *
import coral
import copy
from coral import modeler
import qt
from coral.modeler.coralmodeler import CoralModeler
from coral import ModelCopy,ModelCopy_One
from coral.modeler import xmidigraphbuilder
DI = coral.lang.XMIDI20
import coral.modeler.diagram.xmidi_diagrams as diagrams
from coral.addins.Manage10 import manager
import sys,traceback
from coral.modeler.diagram.degen import DiagramElementGenerator


class ModelManagementMenu(ContextMenuAction):


    def createMenuItem(self,menu,lElement,lPresentation=[], diagram=None, position=None):


    
        self.diagram = diagram
        self.elements = lElement
        self.position = position
        self.presentation=None
        
        if lElement:
            self.element=lElement[0]
        else:
            self.element=None

        if lPresentation:
            self.presentation=lPresentation[0]

        if not self.element:
            return

        if isinstance(self.element,coral.Project):
            return
        
        if self.element.oclIsKindOf(coral.lang.Manage10.ManagedModel):
            mmMenu=qt.QPopupMenu(menu,"Model Management...")

            mmMenu.insertItem("Clone model",self.cloneModel,)
            mmMenu.insertItem("Unrelaible transformation",self.crashModel)
            mmMenu.insertItem("Merge UML 1.4 models",self.mergeUML)
            mmMenu.insertItem("Refine model...")
            mmMenu.insertItem("Transform model...")
            menu.insertItem("Model Management...",mmMenu)

        if self.element.oclIsKindOf(coral.lang.Manage10.Step):
            mmMenu=qt.QPopupMenu(menu,"Model Management...")

            mmMenu.insertItem("Execute direct mapping...",self.executeTransformationMenuOption)
            mmMenu.insertItem("Execute reverse mapping...",self.executeReverseTransformationMenuOption)
            menu.insertItem("Model Management...",mmMenu)

            

    def createAPresentation(self,element,diagram,x,y):
        presentation=None
        deg = DiagramElementGenerator.getExtension(element.__type__())
        if deg and self.presentation:
            presentation = deg.createDiagramElement(element, position=DI.Point(x=x,y=y))
            if presentation:
                diagram.contained.append(presentation)
        return presentation

    def createALink(self,link,p1,p2,diagram):
        de=None
        deg = DiagramElementGenerator.getExtension(link.__type__())
        if deg and self.presentation:
            anchor0 = DI.GraphConnector(graphElement=p1 , position=DI.Point())
            anchor1 = DI.GraphConnector(graphElement=p2 , position=DI.Point())
            de = deg.createDiagramElement(link)
            if de:
                de.anchor.append(anchor0)
                de.anchor.append(anchor1)
                p1.anchorage.append(anchor0)
                p2.anchorage.append(anchor1)
                diagram.contained.append(de)
        return de


    def executeTransformationMenuOption(self,id):
        return self.executeTransformation(self.element)

    def executeReverseTransformationMenuOption(self,id):
        return self.executeTransformation(self.element,dir=-1)
    
    def executeTransformation(self,transformation,dir=1):
        coral.getTransactionManager().beginModifyCmd()
        try:
            if dir==1:
                modulename=string.join(string.split(str(transformation.transformation),'.')[:-1],".")
                funcName=string.split(str(transformation.transformation),'.')[-1]
            else:
                modulename=string.join(string.split(str(transformation.reverseMapping),'.')[:-1],".")
                funcName=string.split(str(transformation.reverseMapping),'.')[-1]
            module = getModuleByName(modulename)
            if module:
                if not module.__dict__.has_key(funcName):
                    raise "Extension "+modulename+" does not have a feature named "+funcName
                pythonFunction=module.__dict__[funcName]

                pythonFunction(transformation)

            for p in transformation.inputParameter:
                p.sourceHasChanged=False
                p.targetHasChanged=False
                manager.cleanParameter(p)
                
            for p in transformation.outputParameter:
                p.sourceHasChanged=False
                p.targetHasChanged=False
                manager.cleanParameter(p)
            transformation.error=False
            transformation.errorMessage=""
        except:
            transformation.error=True
            etype, value, tb = sys.exc_info()
            transformation.errorMessage=str(traceback.format_exception(etype,value,tb))
            for p in transformation.outputParameter:
                p.sourceHasChanged=True
                manager.cleanParameter(p)
            coral.getTransactionManager().endModifyCmd()
        else:
            coral.getTransactionManager().endModifyCmd()


                
    def cloneModel(self,id):
        self.createTransformation(name="Clone",directMapping="coral.addins.Manage10.transformations.clone")
    def mergeUML(self,id):
        self.createTransformation(name="Merge",directMapping="coral.addins.Manage10.transformations.mergeUML14")

    def crashModel(self,id):
        self.createTransformation(name="Crash",directMapping="coral.addins.Manage10.transformations.crash", reverseMapping="coral.addins.Manage10.transformations.crash")

    def createTransformation(self,name,directMapping,reverseMapping="",execute=1):
        
        coral.getTransactionManager().beginModifyCmd()
        try:
            op=coral.lang.Manage10.Step(name=name,manager=self.element.manager)
            op.directMapping=directMapping
            op.reverseMapping=reverseMapping
            opP=self.createAPresentation(op,self.diagram,self.presentation.position.x+150,self.presentation.position.y)
                    
            target=coral.lang.Manage10.ManagedModel(name=self.element.name,manager=self.element.manager)

            
            targetP=self.createAPresentation(target,self.diagram,self.presentation.position.x+250,self.presentation.position.y)
            inp=  coral.lang.Manage10.InputParameter(name="input",source=self.element,targetTransformation=op)
            self.element.manager.managedRelationship.append(inp)
            
            outp=  coral.lang.Manage10.OutputParameter(name="output",target=target,sourceTransformation=op)
            self.element.manager.managedRelationship.append(outp)
            

            self.createALink(inp,self.presentation,opP,self.diagram)
            self.createALink(outp,opP,targetP,self.diagram)

            if execute:
                self.executeTransformation(op)
        finally:
            coral.getTransactionManager().endModifyCmd()

    

class MenuDispatch:
    def __init__(self,method,args):
        self.method =method
        self.args=args
    def doIt(self,id):
        return self.method(*args)



