# -*- coding: utf-8 -*-

import logging
from queue import *
from threading import Thread
from bluefang import commands
from typing import Any

class L2CAPClientThread(Thread):
    def __init__(self, socket: Any, address: str, q: Queue) -> None:
        Thread.__init__(self)
        self.socket = socket
        self.address = address
        self.q = q

    def run(self) -> None:
        logging.info("Sending on address: {0}".format(self.address))
        while True:
            command = self.q.get()
            self.process_command(command)
            self.q.task_done()
    
    def process_command(self, command: str) -> None:
        logging.info("Received command: " + command)
        # Keyboard Reports
        if command == commands.LEFT:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.RIGHT:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.UP:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.DOWN:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.ENTER:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.CANCEL:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.MUTE_VOLUME:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.VOLUME_UP:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.VOLUME_DOWN:
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        # Consumer Reports
        elif command == commands.PLAY:
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.PAUSE:
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.NEXT_TRACK:
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        elif command == commands.PREV_TRACK:
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
            self.socket.send(bytes(bytearray((0xA1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))))
        else:
            logging.warning("Unknown command: " + command)


class L2CAPServerThread(Thread):
    SIZE = 500

    def __init__(self, socket: Any, address: str) -> None:
        Thread.__init__(self)
        self.socket = socket
        self.address = address
    
    def run(self) -> None:
        logging.info("Receiving on address: {0}".format(self.address))
        while 1:
            data = self.socket.recv(L2CAPServerThread.SIZE)
            if data:
                self.process(data)
    
    def process(self, data: Any) -> None:
        logging.debug("Received data:")
        logging.debug(':'.join(hex(x) for x in data))
        if data[0] == 0x71:
            logging.info("Server wants to use Report Protocol Mode. Acknowledging.")
            self.socket.send(chr(0x00)) # Acknowledge that we will use this protocol mode
            self.socket.send(chr(0xA1) + chr(0x04))

"""
Every message should have the following:

L2CAP Length (2 bytes)
L2CAP CID (2 bytes)
HIDP Header (1 byte)
HID Payload (variable)
"""
