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

import string
from coral import log
logger=log.getLogger("degen")
import coral

from coral.modeler import extension

DI = coral.lang.XMIDI20

# Helper functions for the different DEG Classes
def searchForSimpleGraphNode(cset, ti):
    """Search a set of graph elements for graphnode with typeInfo 'ti'."""
    i = -1
    for c in cset:
        i += 1
        if c.semanticModel.oclIsKindOf(DI.SimpleSemanticModelElement) and c.semanticModel.typeInfo == ti:
            return c, i
    return None, -1

def geInDiagram(ge_list,diagram):
    """Return a list containing the graph elements that are in the
    diagram 'diagram'."""
    return [g for g in ge_list if g.__getRoot__() == diagram ]

## When a reparenting is in progress, we store away the
## graphnode and its parent, so that the synchronization
## can fing its associated graphnode

h_reparenting = {}

def addForReparenting(parent_di, child_di, x, y):
    global h_reparenting
    try:
        h_reparenting[parent_di]
    except:
        h_reparenting[parent_di] = []
        
    h_reparenting[parent_di].append( (child_di, x, y) )


def getListOfReparentedGNs(parent_di):
    global h_reparenting
    try:
        l = h_reparenting[parent_di]
    except:
        return []
    del h_reparenting[parent_di]
    return l





class CannotAttachChildException( Exception ):
    pass

class IgnoreThisXMIDICreation ( Exception ):
    pass

empty_list = [ None ]


class __DiagramElementGenerator:
    def __init__(self):
        self.extensions={}
        
    def updateExtensions(self,extensionRegistry):
        for entry in extensionRegistry.getRegisteredExtensionsByType(type="DiagramElementCreator"):
            ed=extension.fromFullElementName2AbstractElementDefinition(entry[0])
            renderer = entry[1]() # create an instance
            if self.extensions.has_key(ed):
                if renderer not in self.extensions[ed]:
                    self.extensions[ed].append(renderer)
            else:
                self.extensions[ed]=[renderer]

    def getExtensionForElement(self, elementdefinition):
        #assert element and not element.oclIsKindOf(DI.DiagramElement)
        global empty_list
        return self.extensions.get(elementdefinition,empty_list)[0]

    def getExtension(self, elementdefinition):
        r = self.getExtensionForElement(elementdefinition)
        if r:
            return r
        lst = []
        lst = elementdefinition.getAllSuperclasses()#__superclasses__()

        for sup in lst:
            # return as soon as we find the first suitable extension
            r = self.getExtensionForElement(sup)
            if r:
                return r

        return None

class DiagramElementCreatorExt:

    def createDiagramElement( self, modelelement , **kwargs):
        # override this method in subclasses
        assert 0

    def createGraphEdge( self, element, **kwargs ):
        try:
            del kwargs['position']
        except KeyError:
            pass
        ge = DI.GraphEdge(**kwargs)

        if not 'waypoints' in kwargs:
            for point in range(2):
                ge.waypoints.append(DI.Point())
        ge.isVisible = True            
        # Actually the gn already has a SemanticModel that is a
        # SemanticModelBridge. Here we replace the ModelBridge which
        # means that the old one will be deleted
        ge.semanticModel = DI.Uml1SemanticModelBridge(element=element)
        return ge
        
    def createGraphNode( self, element, **kwargs ):
        gn = DI.GraphNode(**kwargs)
        if not 'size' in kwargs:
            if not gn.size:
                gn.size = DI.Dimension()
            gn.size.width=16
            gn.size.height=16
        gn.isVisible = True
        # Actually the gn already has a SemanticModel that is a
        # SemanticModelBridge. Here we replace the ModelBridge which
        # means that the old one will be deleted
        gn.semanticModel = DI.Uml1SemanticModelBridge(element=element)
        return gn
        
        
    def createSimpleGraphNode( self, typeInfo, **kwargs ):
        """Creates and returns a GraphNode with a SimpleSemanticModelElement
        with the given typeInfo"""
        gn = DI.GraphNode(**kwargs)
        if not 'size' in kwargs:
            if not gn.size:
                gn.size = DI.Dimension()
            gn.size.width=16
            gn.size.height=16
        gn.isVisible = True

        # Actually the gn already has a SemanticModel that is a
        # SemanticModelBridge. Here we replace the ModelBridge which
        # means that the old one will be deleted
        gn.semanticModel = DI.SimpleSemanticModelElement(typeInfo=typeInfo)
        return gn

    def createSimpleGraphEdge( self, typeInfo, **kwargs ):
        try:
            del kwargs['position']
        except KeyError:
            pass
        ge = DI.GraphEdge(**kwargs)

        if not 'waypoints' in kwargs:
            for point in range(2):
                ge.waypoints.append(DI.Point())
        ge.isVisible = True            
        # Actually the gn already has a SemanticModel that is a
        # SemanticModelBridge. Here we replace the ModelBridge which
        # means that the old one will be deleted
        ge.semanticModel = DI.SimpleSemanticModelElement(typeInfo=typeInfo)
        return ge

    def createAndAttachChild(self, package, child, child_ext):
        raise CannotAttachChildException

    def attachGraphConnector(self, modelelement):
        pass

    def suitableDiagrams(self):
        return []
    
    def createAndAttachToParent(self, element, parent_xmidi, position=None):
        if parent_xmidi.oclIsKindOf(DI.Diagram):
            if parent_xmidi.semanticModel.typeInfo in self.suitableDiagrams(element,parent_xmidi):
                #
                # This creates the XMI-DI element hierarchy for @element
                #
                xmidi=self.createDiagramElement(element, xparent=parent_xmidi)
                # GraphEdges never have a position
                if position and not xmidi.oclIsKindOf(DI.GraphEdge):
                    xmidi.position = position
                parent_xmidi.contained.append(xmidi)
                return xmidi
        return None

    def isMinorElement(self, element=None, xparent=None):
        return True

    def synchronizeContents(self, element, property, old_am, new_am):
        print "synchronizeContents:"
        print "  element=",element
        print "  property=",property
        print "  old_am=",old_am        
        print "  new_am=",new_am



DiagramElementGenerator = __DiagramElementGenerator()
