#!/usr/bin/env python3
import logging
import socket
import sys
import threading
from threading import Thread, current_thread
from zeroconf import ServiceBrowser, Zeroconf, ServiceInfo
from cuid import cuid

logging.basicConfig(level=logging.INFO)


class Client(object):

  def __init__(self, clientName, clientType) -> None:
    self.name = clientName
    self.type = clientType
    try:
      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      self.sock.bind((socket.gethostname(), 30000))
      self.sock.listen(5)
      sockname = self.sock.getsockname()
      self.ip = sockname[0]
      self.port = sockname[1]
      logging.info("Client IP: %s", self.ip)
      logging.info("Client Port: %s", self.port)
    except Exception as excepti:
      logging.info(f"Could not bind to socket. {excepti}")
      sys.exit()

    info = ServiceInfo(
      type_=self.type + 'local.',
      name=self.name + '.' + self.type + 'local.',
      addresses=[socket.inet_aton(self.ip)],
      port=30000,
      weight=0,
      priority=0,
      properties={},
      server=self.name + '.' + self.type + 'local.'
    )

    zeroconf = Zeroconf()
    logging.info("Registering service...")
    zeroconf.register_service(info)
    logging.info("Service registered...")

    while (True):
      try:
        # move to acceptCommand function
        self.clientsocket, self.cAddress = self.sock.accept()
        listen = threading.Thread(target=self.acceptCommand)
        listen.start()
        listen.join()
      finally:
        print("Unregistering...")
        zeroconf.unregister_service(info)
        zeroconf.close()
        self.sock.close()
        break

  def acceptCommand(self):
    logging.info(f"Connection to {self.cAddress} has been established.")

    while True:
      try:
        data = self.clientsocket.recv(1024)

        if not data:
          return False

        logging.info(f"Received {data.decode()}")
        command = str(data.decode())

        if command:
            execute = threading.Thread(arget=self.call, args=(command))
            execute.start()

      except Exception as e:
        logging.error(e)
        logging.error("acceptCommand read error\n")
        return False

  def call(self, num):
    data = "Return message"
    if (num == "0"):
      logging.info("Recieved 0 - Connection Terminated\n")
      self.clientsocket.send("0".encode())
    elif (num == "1"):
      logging.info("Recieved 1 - Connection Established\n")
      self.clientsocket.send("1".encode())
    elif (num == "2"):
      logging.info("Recieved 2 - Sensor On, Detecting Impacts\n")
      self.clientsocket.send("2".encode())
    elif (num == "3"):
      logging.info("Recieved 3 - Target On\n")
      self.clientsocket.send("3".encode())
    elif (num == "4"):
      logging.info("Recieved 4 - Turning off sensor\n")
      self.clientsocket.send("4".encode())
    else:
      logging.info("Number not recognized: ", num, "\n")
      self.clientsocket.send("0".encode())


def main():
  pads = []
  type = "_http._tcp."

  for i in range(1):
    name = "Agipad-" + cuid()
    name = name[0:15]
    thread = threading.Thread(
      target=Client,
      args=(name, type)
    )
    pads.append(thread)
    thread.start()

  for i in range(len(pads)):
    pads[i].join()


if __name__ == "__main__":
    main()
