import logging
import time
from threading import Thread

import zmq

from flandre.config import C
from flandre.nodes.Node import Node
from flandre.utils.Msg import KillMsg, SetDeviceSwitchMsg, DeviceSwitchMsg, RefreshDeviceMsg
from flandre.utils.mi import c1_connect, c1_connected, c1_disconnect
from flandre.utils.network import check_port, check_socket

logger = logging.getLogger(__name__)


class Mi(Node):
    topics = [SetDeviceSwitchMsg, RefreshDeviceMsg]

    def __init__(self, level=logging.INFO):
        super(Mi, self).__init__(level=level)
        self.ping1enable = False
        self.ping60enable = False

    def custom_setup(self):
        self.mi_rep_socket = self.context.socket(zmq.REP)
        self.mi_rep_socket.bind(f"tcp://*:{C.mi_rep_port}")

        self.device_py_req_socket = self.context.socket(zmq.REQ)
        self.device_py_req_socket.connect(C.device_py_rep_socket)

        self.device_py_req_socket1s = self.context.socket(zmq.REQ)
        self.device_py_req_socket1s.connect(C.device_py_rep_socket)

        self.device_py_req_socket60s = self.context.socket(zmq.REQ)
        self.device_py_req_socket60s.connect(C.device_py_rep_socket)

        self.ping1s_thread = Thread(target=self.ping1s)
        self.ping1s_thread.start()
        self.ping60s_thread = Thread(target=self.ping60s)
        self.ping60s_thread.start()

        self.c.poller.register(self.mi_rep_socket, zmq.POLLIN)

    def ping1s(self):
        while True:
            if self.ping1enable:
                self.device_py_req_socket1s.send(b'get_device_status')
                match self.device_py_req_socket1s.recv():
                    case b'on':
                        self.send(DeviceSwitchMsg('GREEN'))
                        self.ping1enable = False
                        self.ping60enable = True
                        self.device_py_req_socket1s.send(b'start')
                        self.device_py_req_socket1s.recv()
                    case b'off':
                        pass
                    case b'err':
                        self.send(DeviceSwitchMsg('ORANGE'))
                        self.ping1enable = False
            time.sleep(1)

    def ping60s(self):
        while True:
            if self.ping60enable:
                self.device_py_req_socket60s.send(b'get_device_status')
                match self.device_py_req_socket60s.recv():
                    case b'off' | b'err':
                        self.send(DeviceSwitchMsg('ORANGE'))
                        self.ping60enable = False
                self.device_py_req_socket60s.send(b'get_driver_status')
                match self.device_py_req_socket60s.recv():
                    case b'off' | b'err':
                        self.send(DeviceSwitchMsg('ORANGE'))
                        self.ping60enable = False
            time.sleep(10)

    def start(self):
        self.device_py_req_socket.send(b'start')
        self.device_py_req_socket.recv()

    def loop(self):
        if c1_connected() and check_socket(C.device_py_rep_socket):
            self.device_py_req_socket.send(b'get_device_status')
            r = self.device_py_req_socket.recv()
            if r == b'on':
                self.device_py_req_socket.send(b'get_driver_status')
                r = self.device_py_req_socket.recv()
                if r == b'on':
                    self.send(DeviceSwitchMsg('GREEN'))
                else:
                    self.send(DeviceSwitchMsg('ORANGE'))
            else:
                self.send(DeviceSwitchMsg('YELLOW'))
                self.ping1enable = True
        while True:
            r = dict(self.c.poller.poll())
            # if self.mi_rep_socket in r:
            #     msg = self.mi_rep_socket.recv()
            #     if msg == b'c1_connected':
            #         c1_connected()
            #
            #     if msg == b'c1_connect':
            #         c1_connect()
            #     if msg == b'c1_disconnect':
            #         c1_disconnect()
            #     self.mi_rep_socket.send(b'ok')
            if self.c.sub in r:
                msg = self.recv()
                logger.info(f'{msg}')
                if isinstance(msg, KillMsg):
                    if msg.name == '':
                        return
                if isinstance(msg, SetDeviceSwitchMsg):
                    if msg.value:
                        c1_connect()
                        self.ping1enable = True
                    else:
                        self.ping60enable = False
                        c1_disconnect()
                        self.device_py_req_socket.send(b'kill')
                        self.device_py_req_socket.recv()
                        self.send(DeviceSwitchMsg('RED'))
                elif isinstance(msg, RefreshDeviceMsg):
                    self.device_py_req_socket.send(b'kill')
                    self.device_py_req_socket.recv()
                    self.device_py_req_socket.send(b'start')
                    self.device_py_req_socket.recv()
                    self.send(DeviceSwitchMsg('GREEN'))
                    self.ping60enable = True
