package kr.co.icontrols.iotplatform.Mqtt;

import android.app.Activity;
import android.content.Context;
import android.widget.Toast;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.internal.StaticCredentialsProvider;
import com.amazonaws.mobileconnectors.iot.AWSIotMqttClientStatusCallback;
import com.amazonaws.mobileconnectors.iot.AWSIotMqttManager;
import com.amazonaws.mobileconnectors.iot.AWSIotMqttNewMessageCallback;
import com.amazonaws.mobileconnectors.iot.AWSIotMqttQos;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;

import java.util.ArrayList;

import kr.co.icontrols.iotplatform.IotPlatformApplication;
import kr.co.icontrols.iotplatform.R;
import kr.co.icontrols.iotplatform.TestIotMqttActivity;

import static kr.co.icontrols.iotplatform.utils.CommonUtils.DebugLogOutput;

public class MqttController {

    private static String TAG = "MqttController";
    private static String COGNITO_POOL_ID = "ap-northeast-2:0e617292-1b9c-4208-b64b-b2d03729b25b";
    private static String TOPIC = "androidDemoTopic";
    private static String ACCOUNT_END_POINT_PREFIX = "a139udwm0q3u52-ats";
    private static String END_POINT = "wss://a139udwm0q3u52-ats.iot.ap-northeast-2.amazonaws.com";
    private static String ACCESS_KEY = "AKIAUSTWEOGGE4XFHBWL";
    private static String SECRET_KEY = "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";

    private static int STATUS_DISCONNECTED = 0;
    private static int STATUS_CONNECTING = 1;
    private static int STATUS_RECONNECTING = 2;
    private static int STATUS_CONNECTED = 3;

    private static MqttController instance;

    private static AWSCredentials awsCredentials;
    private static AWSCredentialsProvider credentialsProvider;
    //private static CognitoCachingCredentialsProvider credentialsProvider;
    private static AWSIotMqttManager mqttManager;

    private ArrayList<String> topicList = new ArrayList<>();

    private static int status_mqtt = STATUS_DISCONNECTED;

    public static MqttController getInstance() {
        return instance;
    }

    public static void init(Context context) {
        if (instance == null) {
            instance = new MqttController();
        }

        /*
        //Amazon Cognito 인증 공급자를 초기화합니다
        credentialsProvider = new CognitoCachingCredentialsProvider(
                getApplicationContext(),
                COGNITO_POOL_ID, // 자격 증명 풀 ID
                Regions.AP_NORTHEAST_2 // 리전
        );
        */

        //Amazon Cognito 인증 공급자를 초기화합니다
        credentialsProvider = new StaticCredentialsProvider(
                new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));

        //intialize unnqique clientid as client to iot aws
        Long tsLong = System.currentTimeMillis()/1000;
        String clientId = tsLong.toString();

        mqttManager = new AWSIotMqttManager(
                clientId/*"android_iot_app_test_mqtt"*/,
                Region.getRegion(Regions.AP_NORTHEAST_2),
                ACCOUNT_END_POINT_PREFIX
        );

        mqttManager.setCleanSession(true);
        mqttManager.setKeepAlive(30);

        new Thread(new Runnable() {
            @Override
            public void run() {
                awsCredentials = credentialsProvider.getCredentials();

                if(credentialsProvider != null && status_mqtt == STATUS_DISCONNECTED) {
                    // connect to AWS IoT using credentials provider
                    mqttManager.connect(credentialsProvider, new AWSIotMqttClientStatusCallback() {
                        @Override
                        public void onStatusChanged(AWSIotMqttClientStatus status, Throwable throwable) {
                            if (status == AWSIotMqttClientStatus.Connecting) {
                                status_mqtt = STATUS_CONNECTING;
                                DebugLogOutput(TAG, "connecting");
                            } else if (status == AWSIotMqttClientStatus.Connected) {
                                status_mqtt = STATUS_CONNECTED;
                                DebugLogOutput(TAG, "connected");
                            } else if (status == AWSIotMqttClientStatus.Reconnecting) {
                                if (throwable != null) {
                                    DebugLogOutput(TAG, "Connection error(Reconnecting). / " + throwable);
                                }
                                status_mqtt = STATUS_RECONNECTING;
                            } else if (status == AWSIotMqttClientStatus.ConnectionLost) {
                                if (throwable != null) {
                                    DebugLogOutput(TAG, "Connection error(ConnectionLost). / " + throwable);
                                    throwable.printStackTrace();
                                }
                                status_mqtt = STATUS_DISCONNECTED;
                            } else {
                                status_mqtt = STATUS_DISCONNECTED;
                            }
                        }
                    });
                }
            }
        }).start();
    }

    public void subscribeToTopic(final String topic,final AWSIotMqttNewMessageCallback callback) {
        DebugLogOutput(TAG, "MQTT call subscribeToTopic : " + topic);
        if(isConneted()) {
            // subscribe to MQTT topic
            mqttManager.subscribeToTopic(topic, AWSIotMqttQos.QOS0, callback);
            topicList.add(topic);
        } else {
            DebugLogOutput(TAG, "MQTT NOT CONNECTED(subscribeToTopic)");
        }

    }

    public void unsubscribeToTopic(String topic) {
        DebugLogOutput(TAG, "MQTT call unsubscribeToTopic : " + topic);
        if(isConneted()) {
            // unsubscribe to MQTT topic
            mqttManager.unsubscribeTopic(topic);
            topicList.remove(topic);
        } else {
            DebugLogOutput(TAG, "MQTT NOT CONNECTED(unsubscribeToTopic)");
        }
    }

    public void allUnsubscribeToTopics() {
        DebugLogOutput(TAG, "MQTT call allUnsubscribeToTopics");
        if(isConneted()) {
            // unsubscribe to MQTT topic
            for(String s : topicList) {
                mqttManager.unsubscribeTopic(s);
            }
            topicList.clear();
        } else {
            DebugLogOutput(TAG, "MQTT NOT CONNECTED(allUnsubscribeToTopics)");
        }
    }

    public void publish(final String topic, final String payload){

        mqttManager.publishString(payload, topic, AWSIotMqttQos.QOS0);
        DebugLogOutput(TAG, "MQTT PUBLISH / " + topic + "\n" + payload);
    }

    public boolean isConneted() {
        return status_mqtt == STATUS_CONNECTED;
    }
}
