import sys
from concurrent.futures import ThreadPoolExecutor

sys.path.append("..")
# 导入pymysql
import socket
import threading
import time
from datetime import datetime

from async_communication import TimeStatu
import google.protobuf.text_format as tf

import message_pb2 as message
from led_protocol import LedProtocol
from led_protocol import font_library
from led_protocol import string_color
import mytool.db_helper.db_operation as spmng


class led_control(threading.Thread):
    def __init__(self, unit, channel, communication, area_list, db_config):
        threading.Thread.__init__(self)
        self._dispatch_statu = {}
        self.led_communication = communication
        self.area_list = area_list
        self.area_1_show_str_timer = TimeStatu('', 0.1)
        self.area_2_show_str_timer = TimeStatu('', 0.1)
        try:
            self.db = spmng.DBOperation(db_config['db_ip'], db_config['db_port'], db_config['db_name'],
                                        db_config['db_user'], db_config['db_password'])
        except Exception as e:
            print(str(e.args))
        self.channel = channel
        self.unit = unit
        if self.unit == 31 and self.channel == 1:
            self.en_font = font_library["EN32"]
            self.cn_font = font_library["CN32"]
        else:
            self.en_font = font_library["EN16"]
            self.cn_font = font_library["CN16"]

        self.led_protocol = LedProtocol(area_list)
        self._pool = ThreadPoolExecutor()
        self.led_control_init()

    def led_control_init(self):
        font = font_library["EN32"]
        unit_char = ""
        if self.unit == 1:
            unit_char = 'A'
        elif self.unit == 2:
            unit_char = 'B'
        elif self.unit == 11:
            unit_char = 'A1'
        elif self.unit == 12:
            unit_char = 'A2'
        elif self.unit == 13:
            unit_char = 'A3'
        elif self.unit == 14:
            unit_char = 'A4'
        elif self.unit == 21:
            unit_char = 'B1'
        elif self.unit == 22:
            unit_char = 'B2'
        elif self.unit == 23:
            unit_char = 'B3'
        elif self.unit == 24:
            unit_char = 'B4'
        elif self.unit == 25:
            unit_char = 'B5'
        elif self.unit == 31:
            unit_char = 'C1'
            if self.channel == 1:
                font = string_color["WHITE"] + font_library["EN48"]
        elif self.unit == 32:
            unit_char = 'C2'
        self.send_led_msg(0, unit_char, en_font=font, cn_font=self.cn_font)

    def receive_dispatch_statu(self, statu, ex, key):
        self._dispatch_statu[key] = statu

    def get_wait_led_string(self, cmd_queue):
        if len(cmd_queue) == 0:
            return ""
        led_show_string = ""
        for num, cmd in zip(range(0, len(cmd_queue)), cmd_queue):
            led_show_string = led_show_string + "%d#%s " % (num + 1, cmd['car_number'])
        led_show_string = "候车:" + led_show_string
        if self.unit == 31 and self.channel == 1:
            led_show_string = string_color["YELLOW"] + led_show_string
        return led_show_string

    def get_pick_led_string(self, cmd_queue):

        key = "dispatch_%d_statu_port" % self.unit
        if (key in self._dispatch_statu) is False or self._dispatch_statu[key].timeout():
            print('ERROR --- 调度节点未连接----key:%s---------time:%s' % (key, datetime.now()))
            led_show_string = "     故 障！"
            if self.unit == 31 and self.channel == 1:
                led_show_string = string_color["RED"] + led_show_string
        else:
            dispatch_node_statu = message.dispatch_node_statu()
            try:
                tf.Parse(self._dispatch_statu[key].statu, dispatch_node_statu)
                if dispatch_node_statu.plc_carrier_status == 0:
                    led_show_string = "     故 障！"
                    if self.unit == 31 and self.channel == 1:
                        led_show_string = string_color["RED"] + led_show_string
                elif dispatch_node_statu.plc_carrier_status == 4:
                    led_show_string = "     维护中！"
                    if self.unit == 31 and self.channel == 1:
                        led_show_string = string_color["RED"] + led_show_string
                else:
                    if len(cmd_queue) == 0:
                        led_show_string = "等待分配!"
                        if self.unit == 31 and self.channel == 1:
                            led_show_string = string_color["BLUE"] + led_show_string
                    else:
                        led_show_string = cmd_queue[0]['car_number'] + " 取车中，请稍候！"
                        if self.unit == 31 and self.channel == 1:
                            led_show_string = string_color["GREEN"] + led_show_string
            except Exception:
                print('ERROR --- 调度状态消息解析错误  key:%s   time:%s    message:\n%s' % (
                    key, datetime.now(), self._dispatch_statu[key].statu))
                led_show_string = "     故 障！"
                if self.unit == 31 and self.channel == 1:
                    led_show_string = string_color["RED"] + led_show_string
        return led_show_string

    # 发送LED消息
    def send_led_msg(self, area_index, input, en_font=font_library["EN32"], cn_font=font_library["CN32"]):

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        try:
            sock.connect((self.led_communication['ip'], self.led_communication['port']))
            time.sleep(0.1)
            sock.send(self.led_protocol.string2bytes(area_index, input, en_font=en_font, cn_font=cn_font))
            print("connected led \033[0:32mSUCCEND\033[m ip:%s   port:%d\nsend msg area_index:%d   msg:%s" % (
                self.led_communication['ip'], self.led_communication['port'], area_index, input))
        except Exception as e:
            print("connected led \033[0:31mERROR\033[m: %s    time:%s   msg=%s" % (str(e.args), datetime.now(), input))
        time.sleep(0.1)
        sock.close()

    #

    def run(self):
        i = 0
        while True:
            time.sleep(1)
            if i == 20:
                self.led_control_init()
                time.sleep(0.1)
                i = 0
            i = i + 1

            wait_cmd_dict = self.db.query_pick_command_in_unit_and_statu(self.unit, 0)
            pick_cmd_dict = self.db.query_pick_command_in_unit_and_statu(self.unit, 1)
            if wait_cmd_dict is None or pick_cmd_dict is None:
                continue
            led_wait_string = self.get_wait_led_string(wait_cmd_dict)
            led_pick_string = self.get_pick_led_string(pick_cmd_dict)

            # test
            # self._pool.submit(self.send_led_msg, 1, str(i),self.en_font,self.cn_font)
            # i = i +1

            if self.area_1_show_str_timer.statu != led_wait_string or self.area_1_show_str_timer.timeout():
                self.area_1_show_str_timer = TimeStatu(led_wait_string, 20)
                self._pool.submit(self.send_led_msg, 1, led_wait_string, self.en_font, self.cn_font)

            if self.area_2_show_str_timer.statu != led_pick_string or self.area_2_show_str_timer.timeout():
                self.area_2_show_str_timer = TimeStatu(led_pick_string, 20)
                self._pool.submit(self.send_led_msg, 2, led_pick_string, self.en_font, self.cn_font)
