import time
import qt

class FakeEvent:
    """The Fake QT event."""
    def __init__(self, x, y, button = 0, keys = 0):
        assert not (button & ~(qt.Qt.LeftButton
                               | qt.Qt.MidButton 
                               | qt.Qt.RightButton))
        assert not (keys & ~(qt.Qt.ShiftButton))
        self._x = int(x)
        self._y = int(y)
        self._button = button
        self._keys = keys
        self._state = keys | button

    def x(self):
        return self._x

    def y(self):
        return self._y

    def button(self):
        return self._button

    def state(self):
        return self._state

class FakeMouse:
    """
    A Fake Mouse that remembers its state
    and generates events
    """
    def __init__(self, modelerwindow, diagramView):
        self.mw = modelerwindow
        self.diagramView = diagramView

        self.oldx = 0
        self.oldy = 0
        self.oldbutton = 0
        self.oldkeys = 0

        self.sleep = 0.3

    def x(self):
        """Return current X coordinate."""
        return self.oldx

    def y(self):
        """Return current Y coordinate."""
        return self.oldy
    
    def __pump(self):
        """Pump QT's event loop."""
        self.mw.processEvents()
        time.sleep(self.sleep)
        
    def __send(self, method, e):
        method(e)
        self.__pump()
        
    def press(self, x = None, y = None, button = qt.Qt.LeftButton, keys = 0):
        if x == None:
            x = self.oldx
        if y == None:
            y = self.oldy
        e = FakeEvent(x, y, button, keys)
        self.oldx = x
        self.oldy = y
        self.oldbutton = button
        self.oldkeys = keys
        if button == 0:
            self.__send(self.diagramView.contentsMouseReleaseEvent, e)
        else:
            self.__send(self.diagramView.contentsMousePressEvent, e)

    def depress(self):
        self.press(self.oldx, self.oldy, 0, 0)

    def click(self, x = None, y = None, button = qt.Qt.LeftButton, keys = 0):
        self.press(x, y, button, keys)
        self.depress()

    def deltaMove(self, dx, dy, times):
        ex = self.oldx + dx
        ey = self.oldy + dy
        return self.move(ex, ey, times)
    
    def move(self, ex, ey, times):
        ox = self.oldx
        oy = self.oldy
        dx = (ex - ox) / float(times+1)
        dy = (ey - oy) / float(times+1)
        for i in range(times + 2):
            nx = ox + i * dx
            ny = oy + i * dy
            e = FakeEvent(nx,
                          ny,
                          self.oldbutton,
                          self.oldkeys)
            self.oldx = nx
            self.oldy = ny
            self.__send(self.diagramView.contentsMouseMoveEvent, e)

    def activateAction(self, actionname):
        """Activates an action in the current diagram,
        such as ClassDiagram_CreateClassAction."""
        buttongroup = self.diagramView.editor.toolbar.group
        cnt = buttongroup.count()
        ok = False
        for i in xrange(cnt):
            actionbutton = buttongroup.find(i)
            print "ACTION", actionbutton.getActionName()
            if actionbutton.getActionName() == actionname:
                ok = True
                buttongroup.setButton(i)
                break
        if not ok:
            raise "Could not find action " + actionname
        self.__pump()

