#!/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
from pprint import pprint
import time

clients = []
local_state = abp.GraphState()

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

    pprint(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()))
    server.send_message_to_all(json.dumps(local_state.to_json()))

def new_message(client, server, message):
    if message.startswith("edit:"):
        edit = json.loads(message[5:])
        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", ""))
    print where
    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()