import asyncio
import time

import aiomqtt
import telnetlib3
from extron_audio_matrix_telnet_interpreter import *


async def extron_audio_telnet_status(client, reader):
    while True: #TODO TODO TODO
        output = await reader.readuntil(b']')
        raw_response: str = output.decode().strip()  # strip not necessary? needed for local netcat testing though
        print("Received: " + raw_response + " from Barco")
        parsed = eam_telnet_code_to_field(raw_response)
        if parsed == None:
            continue  # TODO alert for errors
        print(f"Updating topic [{parsed[0]}] with value [{parsed[1]}]")
        await client.publish(f"p1/projectors/main/status/{parsed[0]}", payload=parsed[1])


async def extron_audio_telnet_control(client, writer):
    await client.subscribe("p1/audio_matrix/#")
    async with client.messages() as msgs:
        async for mesg in msgs:
            print(mesg.topic.value)
            if mesg.topic.matches('p1/audio_matrix/+/command/#'):
                # format: <pred>/<audio_matrix>/[input/output]_[%02number]/command/<cmd>
                _cmd = mesg.topic.value.split("/")[-1]
                _payload = mesg.payload.decode()
                _fullio = mesg.topic.value.split("/")[-3]  # TODO is there a better way to do this?
                _io, _id = _fullio.split("_", maxsplit=2)
                ind = int(_id)

                cmd = ActionType.Gain if _cmd == "GAIN" else (ActionType.Mute if _cmd == "MUTE" else None)
                io = IOType.Input if _io == "input" else (IOType.Output if _io == "output" else None)

                extronCmd = field_to_eam_telnet_code(EAMValue(cmd, io, ind, _payload))
                print(f" Received update: [{mesg.topic.value}] with value [{_payload}]")
                print(f"Sending following command to Extron: [{extronCmd.strip()}]..")
                writer.write(extronCmd)
            await asyncio.sleep(0.2)
    pass

# TODO add initial pull
async def shell(reader, writer):
    async with aiomqtt.Client('localhost', 1883) as client:
        task_status_query = asyncio.create_task(extron_audio_telnet_status(client, writer, reader))
        task_control = asyncio.create_task(extron_audio_telnet_control(client, writer))
        await asyncio.gather(task_control)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    #coro = telnetlib3.open_connection('localhost', 1234, shell=shell)
    coro = telnetlib3.open_connection('192.168.192.14', 23, shell=shell)
    reader, writer  = loop.run_until_complete(coro)
    loop.run_until_complete(writer.protocol.waiter_closed)