import time
import config
import zeroconf

import zeroconf_detect
import formlabs_sender

class ZeroconfDetector(zeroconf_detect.ZeroconfDetector):

    PORT = 35
    FORMLABS_SERVICE_NAME = "_formlabs_formule._tcp.local."

    def detect_formlabs(self, ip):
        discovered_host = None
        usb_info = {"IP": ip, "RUNONCE": True}
        try:
            sender = formlabs_sender.Sender(None, usb_info=usb_info, profile={})
            sender._connect()
            if sender.is_operational():
                alias = None
                if "FORM-2-" in sender.machine_type_id:
                    alias = "FL_FORM2"
                elif "FORM-3-" in sender.machine_type_id or "DGJR-1-" in sender.machine_type_id:
                    alias = "FL_FORM3"
                elif "FRML-3-" in sender.machine_type_id or "DGSR-1-" in sender.machine_type_id:
                    alias = "FL_FRM3L"
                elif "FRMB-3-" in sender.machine_type_id:
                    alias = "FL_FRM3B"
                elif "FRBL-3-" in sender.machine_type_id:
                    alias = "FL_FRM3BL"
                elif "PILK-1-" in sender.machine_type_id:
                    alias = "FL_FUSE1"
                elif "FS30-1-" in sender.machine_type_id:
                    alias = "FL_FUSE1P"
                if alias:
                    printer_profile = [profile for profile in config.get_profiles() if profile['alias'] == alias][0]
                    if printer_profile:
                        vid, pid = printer_profile.get('vids_pids', [("XXXX", "XXXX")])[0]
                        discovered_host = {"IP": ip, "PORT": self.PORT, "SNR": sender.serial_number, "VID": vid, "PID": pid}
                else:
                    self.logger.warning("Detected unsupported FormLabs printer. Save info/status response to logs")
                    info = sender._get_printer_info_tcp()
                    status = sender._get_printer_status_tcp()
                    self.logger.info(str(info))
                    self.logger.info(str(status))
            # disconnecting from printer
            sender._close_tcp_client()
        except RuntimeError as e:
            self.logger.warning("Unable to connect to FormLabs printer")
        return discovered_host

    def detect(self, already_know_ip=None, non_default_port=None):
        if non_default_port:
            self.port = non_default_port
        if already_know_ip:
            if self.check_ip(already_know_ip):
                discovered_host = self.detect_formlabs(already_know_ip)
                if not discovered_host:
                    self.logger.warning("Serial number detecting failed. Can't discover %s" % already_know_ip)
                    vid, pid = self.profile.get('vids_pids', [("XXXX","XXXX")])[0]
                    discovered_host = {"IP": already_know_ip, "PORT": self.PORT, "SNR": already_know_ip, "VID": vid, "PID": pid}
                self.discovered_printers.append(discovered_host)
                return
        self.zeroconf = zeroconf.Zeroconf()
        self.browser = zeroconf.ServiceBrowser(self.zeroconf, self.service_name, self)
        count = 100
        sleep_per_loop = self.TIMEOUT / count
        while count:
            time.sleep(sleep_per_loop)
            count -= 1
        self.zeroconf.close()

    def remove_service(self, zeroconf, service_type, name):
        self.logger.debug("Service %s removed" % (name,))

    def update_service(self, zeroconf, service_type, name):
        self.logger.warning("Service %s updated" % (name,))

    def add_service(self, zeroconf, service_type, name):
        info = zeroconf.get_service_info(service_type, name)
        try:
            ip = info.parsed_addresses()[0]
        except:
            self.logger.error('Failed to determine IP address of detected service')
            ip = None
        else:
            # port is not real port on which zeronconf responded, but port belong to printer's API
            self.logger.info(f"Zeroconf service found on {ip}")
            self.logger.debug(f"Service {name} added:\nIP:{ip}\nInfo:{info}")
            if self.check_ip(ip):
                discovered_host = self.detect_formlabs(ip)
                if not discovered_host:
                    vid, pid = self.profile.get('vids_pids', [("XXXX", "XXXX")])[0]
                    discovered_host = {"IP": ip, "PORT": self.PORT, "SNR": ip, "VID": vid,"PID": pid}
                self.logger.info(f"Adding printer: {discovered_host}")
                self.discovered_printers.append(discovered_host)
            else:
                self.logger.debug(f"Skipping host(printer check failed): {discovered_host}")