import SocketServer
import threading, time, json, socket

import Tkinter as tk
from tkinter_widget import TkinterWidget

import particle_interaction_vis

from python_runtime.statecharts_core import Event
from python_runtime.tkinter_eventloop import *

class Root(tk.Tk):
    def __init__(self, msg_queue, output_queue, framerate):
        tk.Tk.__init__(self)
        self.msg_queue = msg_queue
        self.output_queue = output_queue
        self.framerate = framerate
        self.after(5, self.check_msg_queue)
        self.after(5, self.check_output)
    
    def set_controller(self, controller):
        self.controller = controller
        self.ui_reply_port = self.controller.addOutputListener('output')
    
    def check_msg_queue(self):
        while self.msg_queue:
            self.handle_message(self.msg_queue.pop())
        self.after(5, self.check_msg_queue)
    
    def handle_message(self, message):
        decoded_msg = json.loads(message)
        msg_contents = decoded_msg[1]
        if decoded_msg[0] == "POS_OUT":
            if msg_contents[0] == "delete":
                event = Event("delete_particle", "input", [msg_contents[1]])
            elif msg_contents[0] == "created":
                event = Event("create_particle", "input", [msg_contents[1:]])
            else:
                event = Event("move_particle", "input", [msg_contents])
        elif decoded_msg[0] == "COLOR_OUT":
            event = Event("color_particle", "input", [msg_contents])
        elif decoded_msg[0] == "TIME_OUT":
            event = Event("update_time", "input", ["%.2f" % (float(msg_contents) / self.framerate)])
        if event:
            self.controller.addInput(event)
    
    def check_output(self):
        while True:
            reply_msg = self.ui_reply_port.fetch(0)
            if reply_msg == None:
                break
            event_name = reply_msg.getName()
            parameters = reply_msg.getParameters()
            if event_name == "particle_clicked":
                self.output_queue.append("INTERRUPT %i" % parameters[0])
            elif event_name == "delete_selected":
                self.output_queue.append("INTERRUPT delete_selected")
        self.after(5, self.check_output)

class ServerThread(threading.Thread):
    def __init__(self, queue, output_queue):
        threading.Thread.__init__(self)
        self.daemon = True
        self.queue = queue
        self.output_queue = output_queue
    
    def run(self):
        self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serversocket.bind(('', 9999))
        self.serversocket.listen(1)
        self.clientsocket, address = self.serversocket.accept()
        end = '\n'
        total_data = []
        while 1:
            while self.output_queue:
                self.clientsocket.send(self.output_queue.pop() + '\n')
            data = self.clientsocket.recv(8192)
            if end in data:
                total_data.append(data[:data.find(end)])
                self.queue.append(''.join(total_data))
                total_data = []
            else:
                total_data.append(data)
                if len(total_data) > 1:
                    # check if end_of_data was split
                    last_pair = total_data[-2] + total_data[-1]
                    if end in last_pair:
                        total_data[-2]=last_pair[:last_pair.find(end)]
                        total_data.pop()
                        self.queue.append(''.join(total_data))

if __name__ == "__main__":
    msg_queue, output_queue = [], []
    st = ServerThread(msg_queue, output_queue)
    st.start()
    
    root = Root(msg_queue, output_queue, 30)
    root.withdraw()
    
    controller = particle_interaction_vis.Controller(root, (800, 600), TkEventLoop(root))
    TkinterWidget.controller = controller
    root.set_controller(controller)
    
    controller.start()
    root.mainloop()
    
    st.serversocket.close()
    st.clientsocket.close()