# This is a sample Python script.
import json
import asyncio
import socket

import websockets
import os
import subprocess
import time
import uuid

import test_suite


def generate_unique_64_bit_id():
    return uuid.uuid4().int & (1 << 64) - 1


def send_adb_command(command):
    os.system(command)


def escape_string(extras):
    return extras.replace(" ", "\\ ") + "\\"


def format_as_uri(broadcast_id):
    return f"uri:somewear://broadcast/{broadcast_id}"


def format_channels(channels):
    return ",".join(channels)
    pass


class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'


def current_milli_time():
    return round(time.time() * 1000)


def format_ellpased_time(param):
    if param > 60000:
        return str(param / 60000) + " minutes"
    return str(param / 1000) + " seconds"


two_seconds = 2000
timeout = two_seconds


# wait for a message to be received by a device
def format_success(channelStatus):
    s = ""
    for channel in channelStatus:
        if channelStatus[channel]:
            s += f"{bcolors.OKGREEN}{channel}{bcolors.ENDC}, "
        else:
            s += f"{bcolors.FAIL}{channel}{bcolors.ENDC}, "
    return s[:-2]


def waitfor(test):
    start_time = current_milli_time()
    proc = subprocess.Popen(['adb', '-s', test.receiver, 'logcat', '-v', 'time'], stdout=subprocess.PIPE)
    for line in proc.stdout:

        # if we have waited longer than timeout, kill the process
        current_time = current_milli_time()
        if current_time - start_time > test.timeout:
            print(
                f"{bcolors.FAIL}Test Failed {bcolors.ENDC}: Message not received by {test.receiver} in "
                f"\t\t\t\tbroadcast_id: {test.broadcast_id}\n"
                f"\t\t\t\tmessage: {test.extras}\n"
                f"\t\t\t\tchannels: {format_success(test.channelStatus)}\n"
            )

            proc.kill()
            break

        # if we detect the broadcast id in the logcat, kill the process
        try:
            l = line.decode('utf-8').strip()
            if broadcast_id in l:

                c = test.channels
                for channel in c:
                    if channel in l:
                        test.channels.remove(channel)
                        test.channelStatus[channel] = True
                        break

                # if all channels have been received, kill the process
                if len(c) == 0:
                    end_time = current_milli_time()
                    ellapsed_time = format_ellpased_time(end_time - start_time)

                    print(
                        f"{bcolors.OKGREEN}Test Passed {bcolors.ENDC}: \tMessage received by {test.receiver} in {ellapsed_time} \n"
                        f"\t\t\t\tbroadcast_id: {test.broadcast_id}\n"
                        f"\t\t\t\tmessage: {test.extras}\n"
                        f"\t\t\t\tchannels: {format_success(test.channelStatus)}\n")

                    proc.kill()
                    break
        except:
            proc.kill()

    proc.wait()


pi_ip = '192.168.86.38'
local_host = '192.168.86.30'
ip = local_host


async def execute_test(test):
    ip = socket.gethostbyname(socket.gethostname())
    async with websockets.connect(f"ws://{ip}:5000") as websocket:
        print("Sending test: {}".format(json.loads(test)["uuid"]))
        await websocket.send(test)

        # if test.backhaul_receiver_id:
        #     print("Sending test to backhaul: {}".format(json.loads(test)["uuid"]))
        #     await websocket.send(test)
        #     while True:
        #         message = await websocket.recv()
        #         response_json = json.loads(json.loads(message))
        #         print("est response: {}".format(response_json))
        #         if response_json["data"] == test.backhaul_receiver_id:
        #             break
        # else:
        #     message = await websocket.recv()
        #

        message = await websocket.recv()

        response_json = json.loads(json.loads(message))

        print("Test response: {}".format(response_json))

        test_json = json.loads(test)

        ## temporarily adding this to test backhaul
        # if test_json["receiver"] == response_json["data"]["senderId"]:

        # print(f"sender id: {response_json['senderId']} == {test_json['receiver_id']}")
        uuid = str(test_json["uuid"])

        response_data = str(response_json["data"])

        if uuid in response_data:
            print(f"{bcolors.OKGREEN}Test Passed!{bcolors.ENDC} :test passed uuids match")
        else:
            print(f"{bcolors.FAIL}test failed {uuid} not in {response_data} {bcolors.ENDC}")

        # close connection
        await websocket.close()

        # validate tests here


seconds_between_tests = 2


def runTest():
    test = test_suite.cell_backhaul_test
    test.uuid = generate_unique_64_bit_id()
    asyncio.run(execute_test(json.dumps(test.tojson())))
    time.sleep(seconds_between_tests)
    runTest()
    pass


if __name__ == '__main__':
    ## every 2 seconds call method
    # for i in range(1000):
    #     asyncio.run(execute_test(json.dumps(test_suite.test1.tojson())))
    #     asyncio.run(execute_test(json.dumps(test_suite.test2.tojson())))

    runTest()
    # time.sleep(2)
