#!/usr/bin/env python
import coral
import coral.modeler
from coral.modeler import modeler
from coral.modeler.diagram.degen import addForReparenting

TM = coral.getTransactionManager()

L = coral.lang.UML14
DI = coral.lang.XMIDI20

## Checking that original model is OK
m=modeler.ModelerWindow()
prj = m.openProject("testReparenting.xml")
m.main(loop=0)

model = prj.contents().select(lambda x: x.name == "M1")[0]
modeldiagram = prj.contents().select(lambda x: x.name == "CD1")[0]
packagediagram = prj.contents().select(lambda x: x.name == "PD1")[0]

assert model.oclIsKindOf(L.Model)
assert modeldiagram.oclIsKindOf(DI.Diagram)
assert packagediagram.oclIsKindOf(DI.Diagram)

c1 = model.ownedElement.select(lambda x: x.name == "C1")[0]
c2 = model.ownedElement.select(lambda x: x.name == "C2")[0]
c3 = model.ownedElement.select(lambda x: x.name == "C3")[0]
c4 = model.ownedElement.select(lambda x: x.name == "C4")[0]
p1 = model.ownedElement.select(lambda x: x.name == "P1")[0]
p2 = model.ownedElement.select(lambda x: x.name == "P2")[0]


assert c1
assert c2
assert c3
assert c4
assert p1
assert p2

m.getDiagramEditorManager().editorSet.notifyFocusOn(modeldiagram)

m.processEvents()

xc1 = c1.xmidi_get_graphelements()[0]
xc2 = c2.xmidi_get_graphelements()[0]
xc3 = c3.xmidi_get_graphelements()[0]
xc4 = c4.xmidi_get_graphelements()[0]
xp1 = p1.xmidi_get_graphelements()[0]
xp2 = p2.xmidi_get_graphelements()[0]

assert xp1
xp1bc = xp1.contained[1]
assert xp1bc

assert xp2
xp2bc = xp2.contained[1]
assert xp2bc

assert xc1 in modeldiagram.contained
assert xc2 in modeldiagram.contained
assert xc3 in modeldiagram.contained
assert xc4 in modeldiagram.contained
assert xp1 in modeldiagram.contained
assert xp2 in modeldiagram.contained

assert len(modeldiagram.contained) == 6
assert len(packagediagram.contained) == 0

xpos_xp1 = xp1.position.x
ypos_xp1 = xp1.position.y

xpos_xp2 = xp2.position.x
ypos_xp2 = xp2.position.y

## Then we emulate reparenting by using the same method as in the gestures

## Move C1 into P1
TM.beginModifyCmd()
try:
    xc1.position.x = xpos_xp1+10
    xc1.position.y = ypos_xp1+25
    xc1.ui.__getPyValue__().reparent(c1, p1)
    addForReparenting(xp1, xc1, xpos_xp1+10, ypos_xp1+25) 
finally:
    TM.endModifyCmd()

assert len(modeldiagram.contained) == 5
assert len(packagediagram.contained) == 0
assert len(xp1bc.contained) == 1

## Move C2 into P2
TM.beginModifyCmd()
try:
    xc2.position.x = xpos_xp2+10
    xc2.position.y = ypos_xp2+25
    xc2.ui.__getPyValue__().reparent(c2, p2)
    addForReparenting(xp2, xc2, xpos_xp2+10, ypos_xp2+25) 
finally:
    TM.endModifyCmd()

assert len(modeldiagram.contained) == 4

## VERY IMPORTANT: When reparenting to a package, never add it to the diagram
assert len(packagediagram.contained) == 0

assert len(xp2bc.contained) == 1

## Move C3 AND C4 to P1 in the same transaction
## (Emulates reparenting two classes at the same time)

TM.beginModifyCmd()
try:
    xc3.position.x = xpos_xp1+10
    xc3.position.y = ypos_xp1+30+xc1.size.height
    xc3.ui.__getPyValue__().reparent(c3, p1)
    addForReparenting(xp1, xc3, xpos_xp1+10, ypos_xp1+30+xc1.size.height)
    
    xc4.position.x = xpos_xp1+15+xc3.size.width
    xc4.position.y = ypos_xp1+30+xc1.size.height
    xc4.ui.__getPyValue__().reparent(c4, p1)
    addForReparenting(xp1, xc4, xpos_xp1+15+xc3.size.width, ypos_xp1+30+xc1.size.height)    
finally:
    TM.endModifyCmd()

assert len(modeldiagram.contained) == 2
assert len(xp1bc.contained) == 3


## Move C1 back to the diagram
TM.beginModifyCmd()
try:
    xc1.position.x = xpos_xp1+xp1.size.width+10
    xc1.position.y = ypos_xp1+25
    xc1.ui.__getPyValue__().reparent(c1, model)
    addForReparenting(modeldiagram, xc1, xpos_xp1+xp1.size.width+10, ypos_xp1+25)
finally:
    TM.endModifyCmd()


assert len(modeldiagram.contained) == 3
assert len(xp1bc.contained) == 2

## Now C1 and C3 have different parents. Reparent both to P2
TM.beginModifyCmd()
try:
    xc3.position.x = xpos_xp2+15
    xc3.position.y = ypos_xp2+25
    xc3.ui.__getPyValue__().reparent(c3, p2)
    addForReparenting(xp2, xc3, xpos_xp2+10, ypos_xp2+25)
    
    xc1.position.x = xpos_xp2+15+xc3.size.width
    xc1.position.y = ypos_xp2+25
    xc1.ui.__getPyValue__().reparent(c1, p2)
    addForReparenting(xp2, xc1, xpos_xp2+15+xc3.size.width, ypos_xp2+25)    
finally:
    TM.endModifyCmd()


assert len(modeldiagram.contained) == 2
assert len(xp1bc.contained) == 1
assert len(xp2bc.contained) == 3
assert len(packagediagram.contained) == 0


## Now we create a few class in the package p2
## The class should not be added to the package's xmidi nor to the diagram
## Different transactions so we're sure the synch is OK

i=0
classes = []
for z in xrange(0,5):
    TM.beginModifyCmd()
    try:
        new_class = L.Class(name=("New_Class_"+str(i)), namespace=p2)
        classes.append(new_class)
    finally:
        TM.endModifyCmd()

assert len(classes) == 5

for el in classes:
    assert el in p2.ownedElement

assert len(modeldiagram.contained) == 2
assert len(xp1bc.contained) == 1
assert len(xp2bc.contained) == 3
assert len(packagediagram.contained) == 0
