(function umd(root,factory){
	if (typeof module === "object" && typeof exports === "object")
		module.exports=factory();
	else if (typeof define === "function" && define.amd)
		define([],factory);
	else
		root.OPCTechs_MQTT = factory();
})(this, function factory(){
	"use strict";
	
	OPCTechs_MQTT.prototype.Options = function (_config) {
		if (typeof _config == "object" && Object.keys(_config).length > 0) {
			var self = this;
			Object.keys(self._settings).forEach(function(_k){
				// 有傳入且形態相同
				if (_config[_k] && typeof self._settings[_k] == typeof _config[_k]) {
					if (_k == "qos") {
						self._settings[_k] = [0, 1, 2].includes(_config[_k]) ? _config[_k] : 0;
					} else {
						self._settings[_k] = _config[_k];
					}
				} else if (_config[_k]) {
					console.log("Confing[" + _k + "] Type Error");
				}
			});
		}
		return this._settings;
	}
	
	OPCTechs_MQTT.prototype.Publish = function (_nodeValue, _nodeName) {
		try {
			if (!this._objMQTT) {
				throw "MQTT Has Not Been Initialized";
			}
			if (!this._objMQTT.isConnected()) {
				throw "Connection Error";
			}
			var msg = new Paho.MQTT.Message(_nodeValue);
			msg.destinationName = _nodeName;
			msg.qos = this._settings.qos;
			msg.retained = this._settings.retained;
			this._objMQTT.send(msg);
		} catch (e) {
			console.error(e);
		}
	}
	
	OPCTechs_MQTT.prototype.Startup = function () {
		try {
			var self = this;
			// 設置MQTT物件
			self._objMQTT = new Paho.MQTT.Client(self._settings.host, parseInt(self._settings.port), self._settings.client_id);
			// 顯示log
			var _console = function (_message) {
				if (self._settings.console) {
					console.log("[" + (new Date).pattern("yyyy-MM-dd HH:mm:ss") + "] " + _message);
				}
			}
			// 重新連線
			var _fnReStartup = function () {
				if (self._termination || !self._settings.reconnect) {
					self._termination = false;
					return false;
				}
				// 幾秒後重連
				setTimeout(function(){
					self.Startup();
				}, (self._settings.delay_sec > 0 ? self._settings.delay_sec : 10) * 1000);
			};
			// 連線成功的callback
			var _fnSucc = function(_obj) {
				var topics = [];
				if (self._settings.topic_pots.length) {
					topics = self._settings.topic_pots;
				} else {
					var _topic = "";
					switch (self._settings.topic_base.slice(-1)) {
						case "/":
							_topic = self._settings.topic_base + "#";
							break;
						default:
							_topic = self._settings.topic_base;
					}
					topics.push(_topic);
				}
				// 訂閱主題
				topics.forEach(function(key){
					self._objMQTT.subscribe(key, { qos: 0 });
				});
				// LWT Online Send
				if (typeof _obj.invocationContext == "object") {
					Object.keys(_obj.invocationContext).forEach(function(_nodeName){
						var _succ_msg = new Paho.MQTT.Message(_obj.invocationContext[_nodeName]);
						_succ_msg.destinationName = _nodeName;
						_succ_msg.qos = self._settings.lwt_options.qos;
						_succ_msg.retained = self._settings.lwt_options.retained;
						self._objMQTT.send(_succ_msg);
					});
				}
				if (typeof self._fn_succ == "function") {
					self._fn_succ(_obj);
				}
			};
			// 連線失敗的callback
			var _fnFail = function (_rtn) {
				// 發生錯誤
				if (_rtn.errorCode !== 0) {
					_console("Fail :: " + _rtn.errorMessage);
					if (typeof self._fn_fail == "function") {
						self._fn_fail(_rtn);
					}
				}
				// 啟用自動重連
				_fnReStartup();
			};
			// 設定連線掉線的callback
			self._objMQTT.onConnectionLost = function (_rtn) {
				// 發生錯誤
				if (_rtn.errorCode !== 0) {
					_console("Lost :: " + _rtn.errorMessage);
				}
				// 啟用自動重連
				_fnReStartup();
			};
			// 設定接收訊息的callback
			self._objMQTT.onMessageArrived = function (_rtn) {
				// 呼叫接收callback
				if (typeof self._fn_arrived == "function") {
					var _valueString = _rtn.payloadString.trim();
					if (self._settings.json_value && _valueString.length > 0) {
						self._fn_arrived(JSON.parse(_valueString.replaceAll('\\', '')), _rtn.destinationName)
						return;
					}
					self._fn_arrived(_valueString, _rtn.destinationName);
				}
			};
			// 設定接收訊息的callback
			self._objMQTT.onMessageDelivered = function (_rtn) {
				_console("Delivered :: " + _rtn.destinationName);
			};
			var _opts = {
				useSSL: self._settings.use_ssl,
				cleanSession: true,
				mqttVersion: 3,
				onSuccess: _fnSucc,
				onFailure: _fnFail,
				keepAliveInterval: 60
			};
			// 設置心跳時間
			if (!isNaN(Number(self._settings.keep_alive))) {
				_opts.keepAliveInterval = Number(self._settings.keep_alive);
			}
			// 設置帳密
			if (self._settings.username && self._settings.password) {
				_opts["userName"] = self._settings.username;
				_opts["password"] = self._settings.password;
			}
			// 設置LWT
			if (typeof self._settings.lwt_options == "object" && self._settings.lwt_options.enable == true) {
				// MQTT斷線
				var fail_obj = new Paho.MQTT.Message(self._settings.lwt_options.offline_value);
				fail_obj.destinationName = self._settings.lwt_options.topic;
				fail_obj.qos             = self._settings.lwt_options.qos;
				fail_obj.retained        = self._settings.lwt_options.retained;
				_opts["willMessage"] = fail_obj;
				// MQTT連線
				var succ_obj = {};
				succ_obj[self._settings.lwt_options.topic] = self._settings.lwt_options.online_value;
				_opts["invocationContext"] = succ_obj;
				// 啟用LWT 必須設置心跳時間
				_opts.keepAliveInterval = (_opts.keepAliveInterval == 0 ? 60 : _opts.keepAliveInterval);
			}
			// 建立連線
			self._objMQTT.connect(_opts);
		} catch (e) {
			console.error(e);
		}
	}
	
	OPCTechs_MQTT.prototype.Shutdown = function () {
		try {
			this._termination = true;
			if (!this._objMQTT) {
				throw "MQTT Has Not Been Initialized";
			}
			if (this._objMQTT.isConnected()) {
				this._objMQTT.disconnect();
			}
		} catch (e) {
			console.error(e);
		}
	}
	// 設置收值回調
	OPCTechs_MQTT.prototype.SetFnArrived = function (_callback) {
		this._fn_arrived = _callback;
	}
	// 設置連線成功回調
	OPCTechs_MQTT.prototype.SetFnSucc = function (_callback) {
		this._fn_succ = _callback;
	}
	// 設置連線失敗回調
	OPCTechs_MQTT.prototype.SetFnFail = function (_callback) {
		this._fn_fail = _callback;
	}
	
	function OPCTechs_MQTT () {
		var tmp_client_id = "JS_" + (new Date()).getTime().toString();
		this._settings = {
			host : document.domain,
			port : "1884",
			topic_base: "Sunware/",
			topic_pots: [],
			username : "",
			password : "",
			client_id : tmp_client_id,
			reconnect : true,  // 自動重新連線
			delay_sec : 10,    // 幾秒後重連
			json_value : false, // 接受字串是否為json
			qos : 0,     // 0, 1, 2
			retained : true,  // server是否留存
			keep_alive: 60,
			lwt_options: { // Last Will and Testament setup
				enable: false, // 是否啟用
				topic: "Sunware/Clients/" + tmp_client_id + "/Online",
				online_value: "1",    // online payloadString
				offline_value: "0",   // offline payloadString
				qos: 1,               // 0, 1, 2
				retained: true
			},
			use_ssl: false,
			console: false
		}
		// 終止連線狀態
		this._termination = false;
		// MQTT物件
		this._objMQTT = null;
		// 相關回調函數
		this._fn_arrived = null;
		this._fn_succ = null;
		this._fn_fail = null;
	}
	
	return OPCTechs_MQTT;
});