package com.bjzc.bhzhgd.utils;


/**
 * @author huangwenfei
 * @version v1.0.0.0
 * Created DateTime 2021-03-08 14:52
 * @description: mqtt 高可靠，断线重连 消息发布服务
 */

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;

import com.bjzc.bhzhgd.contans.Contans;
import com.google.gson.Gson;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

import javax.net.ssl.SSLSocketFactory;

public class MqttSSLPublishServer {
    /**
     * 代理服务器ip地址
     */
    //private final String HOST = "tcp://39.101.173.20:1883";
    private final String HOST = "ssl://39.101.173.20:8883";
    //private final String HOST = "tcp://47.242.184.139:8883";
    //private final String HOST = "ssl://47.242.184.139:8883";

    //private final String HOST = "tcp://113.107.214.27:1883";

    /**
     * 发送主题
     */
    private final String topicPush = "app_push_yf";
    /**
     * 订阅主题
     */
    private final String topicReceive = "member_recall";
    /**
     * 客户端唯一标识，相同的会被逼下线
     */
    private String clientid = "v1_server_ssl_android";
    private MqttClient client;
    private MqttConnectOptions options;
    /**
     * MQTT服务端连接账号
     */
    private final String userName = "admin";
    /**
     * MQTT服务端连接密码
     */
    //private final String passWord = "public452131wW452131wW$";
    private final String passWord = "public";
    /**
     * 消息发布质量
     * 0：最多一次，即：<=1
     * 1：至少一次，即：>=1
     * 2：一次，即：=1
     */
    private int qos = 2;
    // 推送消息
    private MqttMessage message;

    private Context context;

    public MqttSSLPublishServer(Context context) {
        this.context=context;
        // host为主机名，clientid即连接MQTT的客户端ID，一般以唯一标识符表示，MemoryPersistence设置clientid的保存形式，默认为以内存保存
        try {
            clientid=(String) SPUtils.get(context,"clientid",String.valueOf(""));
            if(TextUtils.isEmpty(clientid)){
                clientid=UUID.randomUUID().toString();
                SPUtils.put(context,"clientid",clientid);
            }

            client = new MqttClient(HOST, clientid, new MemoryPersistence());
            // MQTT的连接设置
            options = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(false);
            // 设置连接的用户名
            options.setUserName(userName);
            // 设置连接的密码
            options.setPassword(passWord.toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
            options.setKeepAliveInterval(20);
            //断线重连
            options.setAutomaticReconnect(true);
            // 发布目的消息对象
            message = new MqttMessage();
            //mqtt服务器端单向加密
//            SSLSocketFactory socketFactory = MqttSSLSocketFactory.getSingleSocketFactory(context);
//            options.setSocketFactory(socketFactory);
            //mqtt服务器端单双向加密
            SSLSocketFactory socketFactory = MqttSSLSocketFactory.getTwoDirSocketFactory(" ",context);
            options.setSocketFactory(socketFactory);

            // 设置回调
            client.setCallback(new MqttCallbackExtended() {

                @Override
                public void connectComplete(boolean reconnect, String serverURI) {
                    //连接成功后调用
                    try {
                        client.subscribe(topicReceive,qos);//具体订阅代码
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                }

                public void connectionLost(Throwable cause) {
                    //断线后，重新连接
                    try {
                        client.reconnect();
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                }

                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    //收到招回指令
                    String callbackStr = new String(message.getPayload());
                    if(callbackStr.length()>0){
                        Log.i("app",callbackStr);
                    }
                }

                public void deliveryComplete(IMqttDeliveryToken token) {
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            message.setQos(qos);
            message.setRetained(true);
            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String usernameTemp = (String) SPUtils.get(context, Contans.USERID,String.valueOf(""));
            String passwordTemp = (String) SPUtils.get(context,Contans.USERPWD,String.valueOf(""));
            String username =RSAUtils.decryptBASE64StrLocal(usernameTemp);
            String password = RSAUtils.decryptBASE64StrLocal(passwordTemp);
            String nfc = (String) SPUtils.get(context,Contans.NFCBM,String.valueOf(""));

            HashMap<String, String> mapPush = new HashMap<>();
            mapPush.put("username",username);
            mapPush.put("password",password);
            mapPush.put("date",sd.format(new Date()));
            mapPush.put("appversion", getVersionName());
            mapPush.put("nfc",nfc);
            Gson gson = new Gson();
            try {
                //判断拦截状态，这里注意一下，如果没有这个判断，是非常坑的
                if (!client.isConnected()) {
                    // 重新连接
                    client.connect(options);
                    // 订阅
                    client.subscribe(topicReceive,qos);
                }
                if (client.isConnected()) {//连接成功，跳出连接
                    // 发布消息
                    String messageEn = RSAAndroid.encryptByPublicKeyForSpiltStr(gson.toJson(mapPush),RSAAndroid.publicRsaKey);
                    message.setPayload(messageEn.getBytes());
                    client.publish(topicPush, message);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getVersionName() {
        //1,包管理者对象packageManager
        PackageManager pm = this.context.getPackageManager();
        //2,从包的管理者对象中,获取指定包名的基本信息(版本名称,版本号),传0代表获取基本信息
        try {
            PackageInfo packageInfo = pm.getPackageInfo(this.context.getPackageName(), 0);
            //3,获取版本名称
            return packageInfo.versionName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void destroyAll() {
        try {
            if(client.isConnected()){
                client.disconnect();
            }
            // 关闭客户端
            client.close();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}