import json
from http.server import BaseHTTPRequestHandler, HTTPServer
import threading
import requests
import io
import asyncore

jsonserver_hostname = "localhost"
jsonserver_port = 8800

#refserver_hostname = "192.168.68.150"
#refserver_port = 26700
refserver_hostname = "192.168.190.78"
refserver_port = 4001

vMixAPI_address = 'http://localhost:8088/API/'
vMixAPI_TimerInputID = 'TIMER'
vMixAPI_TimerTextField = 'Clock .Text'
vMixAPI_Timer24InputID = 'TIMER'
vMixAPI_Timer24TextField = 'Title Text.Text'
vMixAPI_ColorPlace = '#C7A2E399'
vMixAPI_ColorNone = "#00000000"

game_filename = 'game.json'
homeplayers_filename = 'homeplayers.json'
guestplayers_filename = 'guestplayers.json'

Game = {
    'type': '',
    'home_name': '',
    'guest_name': ''
}

GameHandFutsal = {
    'timer': '',
    'home_fouls': '',
    'guest_fouls': '',
    'home_points': '',
    'guest_points': '',
    'period': '',
    'home_penalties': '',
    'guest_penalties': '',
    'home_timeouts': '',
    'guest_timeouts': '',
    'horn': '',
    'timer_status': '',
    'home_penalty1_player': '',
    'home_penalty2_player': '',
    'home_penalty3_player': '',
    'home_penalty1_timer': '',
    'home_penalty2_timer': '',
    'home_penalty3_timer': '',
    'guest_penalty1_player': '',
    'guest_penalty2_player': '',
    'guest_penalty3_player': '',
    'guest_penalty1_timer': '',
    'guest_penalty2_timer': '',
    'guest_penalty3_timer': ''
}

GameBasketball = {
    'ball_pos':'',
    'timer':'',
    'home_points':'',
    'guest_points':'',
    'period':'',
    'home_fouls':'',
    'guest_fouls':'',
    'home_timeouts':'',
    'guest_timeouts':'',
    'horn':'',
    'timer_status':'',
    'timeout_timer':'',
    'timer24':'',
    'horn24':'',
    'timer24_status':'',
    'timer24_display':'',
}

HomePlayers = [{
    'number': '',
    'name': '',
    'points': '',
    'fouls': ''
} for i in range(0, 16)]

GuestPlayers = [{
    'number': '',
    'name': '',
    'points': '',
    'fouls': ''
} for i in range(0, 16)]


def TimerSet(time):
    #requests.get('{api_address}?Function=SetText&Input={input}&SelectedName={field}&Value={value}'.format(api_address=vMixAPI_address, input=vMixAPI_TimerInputID, field=vMixAPI_TimerTextField, value=time))
    pass

def Timer24Set(time):
    #requests.get('{api_address}?Function=SetText&Input={input}&SelectedName={field}&Value={value}'.format(api_address=vMixAPI_address, input=vMixAPI_TimerInputID, field=vMixAPI_TimerTextField, value=time))
    pass


def dc(v):
    if isinstance(v, int):
        return bytes([v]).decode()
    else:
        return bytes(v).decode()


def pn_ball_pos(v):
    return 'home' if v == 0x31 else ('guset' if v == 0x32 else '')

def pn_timer(v):
    return dc(v[0:2]) + ':' + dc(v[2:4])

def pn_points(v):
    return dc(v.strip())

def pn_period(v):
    return dc(v) if v != 0x30 else 'O'

def pn_teamfouls(v):
    return dc(v) if v != 0x52 else 'red'

def pn_timeouts(v):
    return dc(v)

def pn_horn(v):
    return 1 if v == 0x31 else 0

def pn_startstop(v):
    return 1 if v == 0x30 else 0

def pn_timertimeout(v):
    return dc(v[0]) + ':' + dc(v[1:3])

def pn_timer24(v):
    return dc(v) if 0x30 <= v[1] and v[1] <= 0x39 else dc(v[0]) + '.' + dc(v[1] - 0x10)

def pn_display24(v):
    return 1 if v != 0x30 else 0

def pn_playernumber(v):
    return dc(v)

def pn_playerfouls(v):
    return dc(v)

def pn_penalties(v):
    return dc(v)

def pn_name(v):
    return v.decode('utf-16')

def parce(pkg):
    global GameHandFutsal, GameBasketball, HomePlayers, GuestPlayers

    if len(pkg) < 54:
        print('Error: pkg too short')
        return
    if pkg[0] != 0xf8 or pkg[53] != 0x0d:
        print('Error: Frame uncorrect')
        return

    sport_code = pkg[1]

    if sport_code == 0x33 or sport_code == 0x37 or sport_code == 0x38:
        GameBasketball.update({
            'timer': pn_timer(pkg[4:8]),
            'horn': pn_horn(pkg[19]),
            'timer_status': pn_startstop(pkg[20]),
            'timer24': pn_timer24(pkg[48:50]),
            'horn24': pn_horn(pkg[50]),
            'timer24_status': pn_startstop(pkg[51]),
            'timer24_display': pn_display24(pkg[52])
        })
        
        if GameBasketball['timer24_display'] == 0:
            GameBasketball['timer24'] = ' '

    if sport_code == 0x33:      # BASKETBALL with individual fouls
        Game['type'] = 'Basketball'

        GameBasketball.update({
            'ball_pos': pn_ball_pos(pkg[3]),
            'home_points': pn_points(pkg[8:11]),
            'guest_points': pn_points(pkg[11:14]),
            'period': pn_period(pkg[14]),
            'home_fouls': pn_teamfouls(pkg[15]),
            'guest_fouls': pn_teamfouls(pkg[16]),
            'home_timeouts': pn_timeouts(pkg[17]),
            'guest_timeouts': pn_timeouts(pkg[18]),
            'timeout_timer': pn_timertimeout(bytes([pkg[21]]) + pkg[46:48]),
        })

        for i in range(0, 12):
            HomePlayers[i]['fouls'] = pn_playerfouls(pkg[22 + i])
        for i in range(0, 12):
            GuestPlayers[i]['fouls'] = pn_playerfouls(pkg[34 + i])

        TimerSet(GameBasketball['timer'])
        Timer24Set(GameBasketball['timer24'])
        
   
    elif sport_code == 0x35:      # HANDBALL/FUTSAL
        Game['type'] = 'HandFutsal'

        GameHandFutsal.update({
            'timer': pn_timer(pkg[4:8]),
            'home_fouls': pn_teamfouls(pkg[8]),
            'home_points': pn_points(pkg[9:11]),
            'guest_fouls': pn_teamfouls(pkg[11]),
            'guest_points': pn_points(pkg[12:14]),
            'period': pn_period(pkg[14]),
            'home_penalties': pn_penalties(pkg[15]),
            'guest_penalties': pn_penalties(pkg[16]),
            'home_timeouts': pn_timeouts(pkg[17]),
            'guest_timeouts': pn_timeouts(pkg[18]),
            'horn': pn_horn(pkg[19]),
            'timer_status': pn_startstop(pkg[20]),
            'home_penalty1_player': pn_playernumber(pkg[22:24]),
            'home_penalty2_player': pn_playernumber(pkg[27:29]),
            'home_penalty3_player': pn_playernumber(pkg[32:34]),
            'home_penalty1_timer': pn_playerfouls(pkg[24:27]),
            'home_penalty2_timer': pn_playerfouls(pkg[29:32]),
            'home_penalty3_timer': pn_playerfouls(pkg[34:37]),
            'guest_penalty1_player': pn_playernumber(pkg[37:39]),
            'guest_penalty2_player': pn_playernumber(pkg[42:44]),
            'guest_penalty3_player': pn_playernumber(pkg[47:49]),
            'guest_penalty1_timer': pn_playerfouls(pkg[39:42]),
            'guest_penalty2_timer': pn_playerfouls(pkg[44:47]),
            'guest_penalty3_timer': pn_playerfouls(pkg[49:52])
        })
    
    elif sport_code == 0x36:      # VOLLEYBALL
        pass

    elif sport_code == 0x37:    # Individual points - GUEST BASKET/HAND/HOCKEY/FUTSAL
        for i in range(0, 13):
            GuestPlayers[i]['points'] = pn_points(pkg[22 + 2*i : 24 + 2*i])
        for i in range(13, 16):
            GuestPlayers[i]['points'] = pn_points(pkg[11 + 2*i : 13 + 2*i])
        print(GuestPlayers)

    elif sport_code == 0x38:    # Individual points - HOME BASKET/HAND/HOCKEY/FUTSAL
        for i in range(0, 13):
            HomePlayers[i]['points'] = pn_points(pkg[22 + 2*i : 24 + 2*i])
        for i in range(13, 16):
            HomePlayers[i]['points'] = pn_points(pkg[11 + 2*i : 13 + 2*i])

    elif sport_code == 0x39:    # TENNIS
        pass
    
    elif sport_code == 0x3A:    # TABLE TENNIS
        pass

    elif sport_code == 0x3C:    # HANDBALL with individual penalties
        pass

    elif sport_code == 0x62:    # GUEST NAME
        if pkg[2] == 0x20:
            Game['guest_name'] = pn_name(pkg[6:48])
            with open(game_filename, 'w', encoding='utf-8') as f:
                json.dump(Game, f, ensure_ascii=False, indent=4)
        else:
            GuestPlayers[int(pkg[2])]['number'] = pn_playernumber(pkg[51:53])
            GuestPlayers[int(pkg[2])]['name'] = pn_name(pkg[3:23])
            with open(guestplayers_filename, 'w', encoding='utf-8') as f:
                json.dump(GuestPlayers, f, ensure_ascii=False, indent=4)

    elif sport_code == 0x77:    # HOME NAME
        if pkg[2] == 0x20:
            Game['home_name'] = pn_name(pkg[6:48])
            with open(game_filename, 'w', encoding='utf-8') as f:
                json.dump(Game, f, ensure_ascii=False, indent=4)
        else:
            HomePlayers[int(pkg[2])]['number'] = pn_playernumber(pkg[51:53])
            HomePlayers[int(pkg[2])]['name'] = pn_name(pkg[3:23])
            with open(homeplayers_filename, 'w', encoding='utf-8') as f:
                json.dump(HomePlayers, f, ensure_ascii=False, indent=4)

    elif sport_code == 0x4D:    # MESSAGE
        GameHandFutsal.update({
            'timer': pn_timer(pkg[4:8]),
            'horn': pn_horn(pkg[19]),
            'timer_status': pn_startstop(pkg[20]),
            'timer24': pn_timer24(pkg[48:50]),
            'horn24': pn_horn(pkg[50]),
            'timer24_status': pn_startstop(pkg[51]),
            'timer24_display': pn_display24(pkg[52])
        })

    elif sport_code == 0x41 or sport_code == 0x043:    # MESSAGE CONFIGURATION
        GameHandFutsal.update({
            'timer': pn_timer(pkg[4:8]),
            'horn': pn_horn(pkg[19]),
            'timer_status': pn_startstop(pkg[20]),
            'timer24': pn_timer24(pkg[48:50]),
            'horn24': pn_horn(pkg[50]),
            'timer24_status': pn_startstop(pkg[51]),
            'timer24_display': pn_display24(pkg[52])
        })

    else:
        print('Error: Unknown sport code {}'.format(sport_code))

       
class REFClient(asyncore.dispatcher):
    buff = []

    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket()
        self.connect( (host, port) )

    def handle_connect(self):
        pass
		#print('Connect to referee system is established')

    def handle_close(self):
        self.close()

    def handle_read(self):
        buff = self.recv(8192)
        if len(buff) == 54:
            parce(buff)

class JSONServer(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/Game':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes(json.dumps([GameBasketball]), "utf-8"))

        elif self.path == '/GameBasketball':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes(json.dumps([GameBasketball]), "utf-8"))

        elif self.path == '/GameHandFutsal':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes(json.dumps([GameHandFutsal]), "utf-8"))
			#GameHandFutsal
			#self.wfile.write(bytes(json.dumps([GameHandFutsal]), "utf-8"))

        elif self.path == '/HomePlayers':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes(json.dumps(HomePlayers), "utf-8"))
            
        elif self.path == '/GuestPlayers':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes(json.dumps(GuestPlayers), "utf-8"))

        elif self.path == '/refresh':
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes('[{"refresh":"ok"}]', "utf-8"))

            with io.open('C:/Users/aksma/YandexDisk/workspace/_hd1/_gfx/multisport_452/data.bin', 'rb') as f:
                parce(f.read())
        
        else:
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(bytes('[{"error":"bad path"}]', "utf-8"))

if __name__ == "__main__":

    try:
        with open(game_filename) as f:
            Game = json.load(f)
        with open(homeplayers_filename) as f:
            HomePlayers = json.load(f)
        with open(guestplayers_filename) as f:
            GuestPlayers = json.load(f)
    except:
        pass

    webServer = HTTPServer((jsonserver_hostname, jsonserver_port), JSONServer)
    print("Server started http://%s:%s" % (jsonserver_hostname, jsonserver_port))

    client = REFClient(refserver_hostname, refserver_port)
    
    thread = threading.Thread(target=asyncore.loop, args=())
    thread.start()
    print('Connect to referee system is established')

    try:
        webServer.serve_forever()
    except KeyboardInterrupt:
        pass

    webServer.server_close()
    print("Server stopped.")