from OCC.Display.XDisplay import *
import sys
import SocketServer
import socket
import sys
import time
from code import InteractiveConsole

class RemoteXOCCWindow(XOCCWindow):
    
    def init_server(self, context):
        print "SERVER: window init: "+str(context)
        self.server = PythonServer(('', 50008), context)
    
    def MainLoop(self):
        current = None
        while True:
            #make event handling non-blocking
            while self.d.pending_events() > 0:
                current = self.handle_events(current)
            if hasattr(self, 'server'):
                self.server.handle_request()
            #save the poor processor with some ms of sleep
            time.sleep(0.004)
    
    def handle_events(self, current):
        e = self.d.next_event()
        if not self.viewer_inited:
            self.occviewer.OnResize() #need to be resized in ordre tohave a proper display
            self.viewer_inited = True
        # Window has been destroyed, quit
        if e.type == X.DestroyNotify:
            sys.exit(0)    
        # Some part of the window has been exposed,
        # redraw all the objects.
        elif e.type == X.Expose:
          self.occviewer.OnResize()
           #   o.expose(e)
        # Left button pressed, start to draw
        elif e.type == X.ButtonPress and e.detail == 1:
            current = MoveEvent(self, e)
            #self.objects.append(current)
        # Middle button pressed, start to draw
        elif e.type == X.ButtonPress and e.detail == 2:
            current = MoveEvent(self, e)
            #self.objects.append(current)
        elif e.type == X.ButtonPress and e.detail == 3:
            current = MoveEvent(self, e)
            #self.objects.append(current)
        # Left button released
        elif e.type == X.ButtonRelease and current:# and e.detail == 1 and current:
            current.finish(e)
            current = None
        elif e.type == X.KeyPress:
            key_code = self.d.keycode_to_keysym(e.detail, 0)
            try:
                if isinstance(self._key_map[key_code],type(iter([]))):#iterator type
                    self._key_map[key_code].next()()
                else:
                    self._key_map[key_code]()
            except:
                print 'unrecognized key', key_code
       # Mouse movement with button pressed
        elif e.type == X.MotionNotify and current:
           current.motion(e)
        elif e.type == X.MotionNotify:
            # Motion without any button pressed: selection mode
            self.occviewer.MoveTo(e.event_x,e.event_y)
        elif e.type == X.ClientMessage:
           if e.client_type == self.WM_PROTOCOLS:
               fmt, data = e.data
               if fmt == 32 and data[0] == self.WM_DELETE_WINDOW:
                   sys.exit(0)
        elif e.type == X.ResizeRequest:
            self.window.map()
            self.occviewer.OnResize()
        elif e.type == X.ButtonRelease:
            print "Button Release!!"
            if self.occviewer.Select(e.event_x,e.event_y):
                selected_shape = self.occviewer.GetSelectedShape()
                print selected_shape,selected_shape.ShapeType()
                
        return current    



class PythonServer(SocketServer.TCPServer):
    def __init__(self, server_address, local_context):
        SocketServer.TCPServer.__init__(self, server_address, None)
        self.socket.setblocking(0)
        print "SERVER: console init: "+str(local_context)
        self.console = InteractiveConsole(local_context)

    def run(self):
        while True:
            try:
                self.handle_request()
                #time.sleep(0.1)
            except KeyboardInterrupt:
                print "Closing server"
                self.server_close()


    def finish_request(self, request, client_address):
            """Finish one request by instantiating RequestHandlerClass."""
            #self.RequestHandlerClass(request, client_address, self)
            data = '***'
            while data:
                try:
                    data = request.recv(1024)
                except:
                    break

                if not data:
                    break

                self.redirect_output()
                complete = self.console.push(data.rstrip())
                output = self.restore_output()
                #output = ""
                if output:
                    request.send(output)
                elif complete:
                    request.send("... ")
                else:
                    request.send(">>> ")

    def redirect_output(self):
        self.saveout = sys.stdout                                     
        sys.stdout = open('stdout.tmp', 'w')
        self.saveerr = sys.stderr 
        sys.stderr = open('stderr.tmp', 'w') 

    def restore_output(self):
        sys.stdout.close()
        sys.stdout = self.saveout
        sys.stderr.close()
        sys.stderr = self.saveerr
        output = ""
        output += open('stdout.tmp', 'r').read()
        output += open('stderr.tmp', 'r').read() 
        print output
        return output