#!/usr/bin/python
"""
This is a simple websocket relay server that facilitates realtime visualization of GraphStates.
It doesn't do much except echo websocket messages to all connected clients, and serve some static content over HTTP.
"""

from websocket_server import WebsocketServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer
from SocketServer import ThreadingMixIn
import os, sys, threading
import webbrowser
import argparse
import abp
import json
from pkg_resources import resource_filename
import time

clients = []
local_state = abp.GraphState()

def process_edit(edit, client, server):
    action = edit["action"]

    print edit

    if action == "create":
        local_state.add_qubit(edit["name"], position=edit["position"], vop=0)
    elif action == "cz":
        local_state.act_cz(edit["start"], edit["end"])
    elif action == "hadamard":
        local_state.act_hadamard(edit["node"])
    elif action == "phase":
        local_state.act_local_rotation(edit["node"], "phase")
    elif action == "delete":
        local_state._del_node(edit["node"])
    elif action == "localcomplementation":
        local_state.local_complementation(edit["node"])
    elif action == "measure":
        local_state.measure(edit["node"], "p"+edit["basis"])
    else:
        pass

    server.send_message(client, json.dumps(local_state.to_json()))

def new_message(client, server, message):
    if message.startswith("edit:"):
        print message[5:]
        edit = json.loads(message[5:])
        print "Received update from javascript."
        process_edit(edit, client, server)
    else:
        print "Received update from python {}.".format(client["id"])
        print message
        local_state.from_json(json.loads(message))
        print local_state
        server.send_message_to_all(message)

def new_client(client, server):
    print "Client {} connected.".format(client["id"])
    clients.append(client)
    print "Sent state of {} nodes to client {}".format(local_state.order(), client["id"])
    server.send_message(client, json.dumps(local_state.to_json()))

def client_left(client, server):
    print "Client {} disconnected.".format(client["id"])
    clients.remove(client)

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """ Handle requests in a separate thread """

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "ABP websocket server")
    parser.add_argument("-v", action="store_true", help="Launch browser")
    args = parser.parse_args()

    # Change to the right working dir
    where = os.path.abspath(resource_filename("abp.static", ""))
    os.chdir(where)

    # Start the HTTP server
    httpserver = ThreadedHTTPServer(('', 5001), SimpleHTTPRequestHandler)
    thread = threading.Thread(target = httpserver.serve_forever)
    thread.daemon = True
    thread.start()

    if args.v:
        webbrowser.open("http://localhost:5001/")

    # Start the websocket server
    server = WebsocketServer(5000)
    server.set_fn_new_client(new_client)
    server.set_fn_message_received(new_message)
    server.set_fn_client_left(client_left)
    server.run_forever()
    httpserver.shutdown()