#!usr/bin/python3
import json
import shlex
import socket
import threading
import time
import paho.mqtt.client as mqtt
import subprocess
import os


class smqtt:
    def __init__(self,  mqtt_info, callback = None, led_callback = None):
        self._topic_enable = False
        self._topic = []
        self._mqtt_enable = False
        self._mqtt_info = mqtt_info
        self._client = None
        self._start_flag = False
        self._rcv_event = threading.Event()
        self._data = None
        self._updata_data = None
        self._callback = callback
        self._led_callback = led_callback
        self._connect_status = False

       
    def open_mqtt(self):
        # open mqtt
        try:
            if 'user' in self._mqtt_info and 'password' in self._mqtt_info \
                    and 'broker' in self._mqtt_info and 'port' in self._mqtt_info:
                self._client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1)
                # self._client.username_pw_set(self._mqtt_info['user'], self._mqtt_info['password'])        
                self._client.on_connect = self.on_connect
                self._client.on_message = self.on_message
                # self._client.connect(self._mqtt_info['broker'], self._mqtt_info['port'])
                self._mqtt_enable = True
            else:
                self._mqtt_enable = False
        except Exception as exp:
            self._mqtt_enable = False
            print(exp)

    def set_add_topic(self, topic):
        self._topic_enable = True
        self._topic.append(topic)

    def get_add_topic(self):
        if self._topic_enable:
            return self._topic
        else:
            return None

    def clear_topic(self):
        del self._topic
        self._topic = []
        self._topic_enable = False

    def on_connect(self, client, userdata, flags, rc):
        if self._topic_enable and self._mqtt_enable:
            for index in self._topic:
                self._client.subscribe(index)
        self._start_flag = True

    def on_message(self, client, userdata, msg):
        try:
            if self._topic_enable and self._mqtt_enable:
                data = str(msg.payload, encoding="utf-8")
                data = eval(data) 
                self._callback(msg.topic, data)            

        except Exception as exp:
            print(exp)

    def publish(self, topic, data):
        try:
            if self._client._state != 2 and self._mqtt_enable and self._connect_status is True:
                self._client.publish(topic, json.dumps(data, separators=(',', ':')), qos=1)
        except Exception as exp:
            print(exp)

    def set_rcv_event(self):
        if self._rcv_event is not None:
            self._rcv_event.set()

    def wait_rcv_event(self):
        if self._rcv_event is not None:
            self._rcv_event.wait()

    def clear_rcv_event(self):
        if self._rcv_event is not None:
            self._rcv_event.clear()

    def get_rcv_data(self):
        return self._updata_data 

    def loop_task(self):
        try:
            if self._mqtt_enable:
                self._client.loop_start()
        except Exception as exp:
            print(exp)

    def del_task(self):
        try:
            if self._mqtt_enable:
                self._client.loop_stop()
        except Exception as exp:
            print(exp)

    def internet_task(self):
        while True:
            try:
                servers = [(self._mqtt_info['broker'], self._mqtt_info['port'])]
                r = self.test_connections_to_servers(servers)
                if r is False:  
                    if self._connect_status is True:
                        self._client.disconnect()
                        self.del_task()
                        self._connect_status = False  
                else:
                    if self._connect_status is False:
                        self._client.username_pw_set(self._mqtt_info['user'], self._mqtt_info['password'])        
                        self._client.connect(self._mqtt_info['broker'], self._mqtt_info['port'])
                        if self._topic_enable and self._mqtt_enable:
                            for index in self._topic:
                                self._client.subscribe(index)
                        self._connect_status = True      
                        self.loop_task()           
            except Exception as exp:  
                # 超时会进入这里
                if self._connect_status is True:
                    self._client.disconnect()
                    self.del_task()
                    self._connect_status = False  
                print(exp)
            time.sleep(60)

    def test_tcp_connection(self, host='8.8.8.8', port=53):
        try:
            cnt = socket.create_connection((host, port), timeout=5)
            cnt.close()
            return True
        except Exception as exp:
            print(exp)
            return False
        
    def test_connections_to_servers(self, servers=[('116.62.127.242', 1883), ('114.114.114.114', 53)]):
        for server, port in servers:
            if self.test_tcp_connection(server, port):
                return True
        return False           
