import asyncio
import time
import logging

import aiohttp
import base_detector
import config


class LocalMoonrakerDetector(base_detector.BaseDetector):

    IP = "127.0.0.1"
    HTTP_PORT = 7125
    PATH = "/server/info"
    URL = "http://" + IP + ":" + str(HTTP_PORT) + PATH
    TIMEOUT = 1
    RETRIES = 3
    LOOP_SLEEP = 1
    SHUTDOWN_WAITING_STEP = 0.01
    PRINTER_ID_LIST = [{'VID': 'MNRK', 'PID': 'GENE', 'SNR': '127.0.0.1', 'IP': '127.0.0.1'}]
    CONFLICTS = ['KlipperDetector']


    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent
        self.devices_list = []
        self.retries_left = 0
        self.lock = asyncio.Lock()
        self.session = None
        port = config.get_settings().get('local_moonraker', {}).get('port')
        if port and port != self.HTTP_PORT:
            try:
                self.PRINTER_ID_LIST[0]['PORT'] = int(port)
            except (ValueError, TypeError):
                logging.getLogger(self.__class__.__name__).error('Invalid port for local Moonraker: ' + str(port))
        self.always_on = config.get_settings().get('local_moonraker', {}).get('always_on')
        if self.always_on:
            self.devices_list = self.PRINTER_ID_LIST
        else:
            try:
                self.loop = asyncio.get_running_loop()
            except RuntimeError:
                self.loop = asyncio.new_event_loop()
            self.get_printers_list = self.detect

    def get_printers_list(self):
        return self.devices_list

    def detect(self):
        self.loop.run_until_complete(self.detection_coro())
        return self.devices_list

    async def detection_coro(self):
        try:
            with self.lock:
                if not self.session:
                    self.session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=self.TIMEOUT))
            async with self.session.get(self.URL) as resp:
                if resp.ok:
                    resp_dict = await resp.json()
                    moonraker_version = resp_dict.get('result', {}).get('moonraker_version')
                    if moonraker_version:
                        self.retries_left = self.RETRIES
                        self.devices_list = self.PRINTER_ID_LIST
        except:
            pass
        if self.retries_left < 1:
            self.devices_list = []
        else:
            self.retries_left -= 1
            await asyncio.sleep(self.LOOP_SLEEP)
