# Copyright (c) 2015 Vibhav Pant <vibhavp@gmail.com>

# Permission is hereby granted, free of charge, to any person obtaining a 
# copy of this software and associated documentation files (the "Software"), 
# to deal in the Software without restriction, including without limitation 
# the rights to use, copy, modify, merge, publish, distribute, sublicense, 
# and/or sell copies of the Software, and to permit persons to whom the 
# Software is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in 
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
# DEALINGS IN THE SOFTWARE.

#!/usr/bin/env python3
import zmq
from websocket import create_connection
import time
import threading
import pyautogui

###################################################################
# The port on which autocamera.py will listen
feed_port = "5555"
# The port on which ExternelExtensions with listen
websockets_port  = "2006"
# The STV delay, in seconds     
stv_delay = 90
# Spectate player when these much seconds are left
spec_on = 5
# bind configured in TF2 to autocamera_spec_player
camera_bind = 'k'
###################################################################

# Stuff after this point shouldn't usually bother you if you're the
# cameraperson
global_lock = threading.Lock()
thread_exit = False;

# an event is a tuple of the form (player, time).
# player is a string containing the name of the player we want to spectate
# time is the timestamp (in seconds) of when the event will take place
event_queue = []


def event_push(player):
    # Only push if the event didn't occur within 5 seconds of the last
    # event
    if (event_queue == [] or int(time.time()) - event_queue[0][1] > 5):
        event_queue.insert(0, (player, int(time.time() + stv_delay)))

def send_events():
    ws = create_connection("ws://127.0.0.1:%s" % websockets_port)

    while True:
        while (event_queue == []):
            if thread_exit:
                exit(0)
            time.sleep(1)

        # Sleep until 5 seconds are left for the event to happen
        global_lock.acquire(True)
        head_time = event_queue[len(event_queue) - 1][1]
        global_lock.release()
        time.sleep(int(time.time()) - head_time + spec_on)

        # Get the player to spec
        global_lock.acquire(True)
        head_player = event_queue[len(event_queue) - 1][0]
        event_queue.pop()
        global_lock.release()
        request = "{ \"type\": \"command\", \"comand\": \"spec_player %s\"}" % head_player
        ws.send(request)

def main():
    feed_context = zmq.Context()
    feed_socket = feed_context.socket(zmq.PAIR)
    feed_socket.bind("tcp://*:%s" % feed_port)

    t = threading.Thread(target=send_events)
    t.start()

    while True:
        name = feed_socket.recv().decode("utf-8")
        if name == "exit":
            global thread_exit
            thread_exit = True
            feed_socket.disconnect("tcp://*:%s" % feed_port)
            exit(0)

        global_lock.acquire(True)
        event_push(name)
        global_lock.release()

if __name__ == "__main__":
    main()

@@ -2223,16 +2223,71 @@
 %5D %3E 5):%0A
+        # The event occurs at current_time + stv_delay%0A
         
@@ -2376,86 +2376,254 @@
     
-ws = create_connection(%22ws://127.0.0.1:%25s%22 %25 websockets_port)%0A%0A    while True:
+# Connect to ExternalExtensions' websocket%0A    print(%22Connecting to ExternalExtensions...%22)%0A    ws = create_connection(%22ws://127.0.0.1:%25s%22 %25 websockets_port)%0A    print(%22Done.%22)%0A    %0A    while True:%0A        # Wait until the event queue isn't empty
 %0A   
@@ -2737,73 +2737,8 @@
 1)%0A%0A
-        # Sleep until 5 seconds are left for the event to happen%0A
     
@@ -2854,24 +2854,25 @@
 lease()%0A
+%0A
         
 time.sle
@@ -2867,38 +2867,98 @@
     
-time.sleep(int(
+# Sleep for (time_when_event_happens - current_
 time
-.time()) - 
+ + spec_on) seconds%0A        time.sleep(
 head
@@ -3079,89 +3079,143 @@
 ueue
-%5Blen(event_queue) - 1%5D%5B0%5D%0A        event_queue.pop()%0A        global_lock.release()
+.pop()%0A        global_lock.release()%0A        # Send request to ExternalExtensions to execute the command%0A        # spec_player %3Cplayer%3E
 %0A   
@@ -3336,24 +3336,29 @@
 def main():%0A
+    %0A
     feed_con
@@ -3542,32 +3542,72 @@
     while True:%0A
+        # Get name of player to observe%0A
         name = f

Add comments explaining code.