var config;
var POLL_DELAY = 5000;
var currentChannel;
var currentYear;
var currentMonth;
var currentDay;
var currentHour;
var currentMinute;
var currentSecond;
var currentTimezone;
var ampm = "";
var SMALL_DEVICE_480 = 480;

//wifi
var wifi = true;
var WIFI_AP = 0;
var WIFI_AH = 1;
var WIFI_CLIENT = 2;
var wifiType = WIFI_AP;
var wifiPw = "";
var ssid = "";
var wifiChannel = 1;
var POLL_WIFIS = 5000;
var userChangedWifiChannel = false;
//var createAP = false;
var createClient = false;
var oldWifiName = "";
//wifi password
var validChars = /^[a-zA-Z0-9\.,:;!\?\+\-@%\(\)\[\]\{\}<>^\|~#\$_]*$/;
// with cirillic characters:
// ^[a-zA-Z0-9\u0080-\u00ad\u00d0-\u00d8\u00dd-\u00de\u00e0-\u00ee\u00f1-\u00fc\.,:;!\?\+\-@%\(\)\[\]\{\}<>^\|~#\$_]*$
var wifiPwError = false;

// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
  hidden = "hidden";
  visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
  hidden = "mozHidden";
  visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
  hidden = "msHidden";
  visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
  hidden = "webkitHidden";
  visibilityChange = "webkitvisibilitychange";
}

/**
 * send settings to gateway when user clicks the submit button
 */
function onSubmit(alertid) {
var setTimeAfterTimezone = false;
    var params = {
        "otauactive" : false,
		"timeformat" : "12h",
		"networkopenduration" : 60,
		"name" : "deGateway",
        "discovery" : false,
		"rgbwdisplay" : "1"
    };

    if ($('#networkUpCheckbox').prop('checked')) {
        params.rfconnected = true;
    }

	if ($('#internetServiceCheckbox').prop('checked')) {
        params.discovery = true;
    }

    if ($('#otauActiveCheckbox').prop('checked')) {
        params.otauactive = true;
    }

	params.name = $("#gwNameInput").val();

	params.timeformat = $('#timeFormat').val();

	//params.rgbwdisplay = $('#rgbwDisplay').val();

	//params.groupdelay = parseInt($("#gwGroupDelayInput").val());

	if (($('#channelSelect').val() != currentChannel) && ($('#channelSelect').val() != 0)) {
		params.zigbeechannel = parseInt($("#channelSelect").val());
	}

	params.networkopenduration = parseFloat($("#networkOpenDuration").val())*60; //min -> sec

	// set time settings only for linux gateway and only when Advanced System Settings are shown
    if ((config.config.system == "linux-gw") && ($('#sysSetText').text() == "Advanced System Settings")) {

		if (checkCorrectTime() == false) {
			return;
		}

		var hourInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwHoursInputPhone').value : document.getElementById('gwHoursInput').value

		var minutesInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwMinutesInputPhone').value : document.getElementById('gwMinutesInput').value

		var secondsInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwSecondsInputPhone').value : document.getElementById('gwSecondsInput').value

		var yearInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwYearInputPhone').value : document.getElementById('gwYearInput').value

		var monthInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwMonthInputPhone').value : document.getElementById('gwMonthInput').value

		var dayInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwDayInputPhone').value : document.getElementById('gwDayInput').value

		if ((currentTimezone != $('.timezoneselect').val())) {

			$('.loading').removeClass('hidden');
			params.timezone = $('.timezoneselect').val();
			currentTimezone = $('.timezoneselect').val();

			//also set time when timezone is changed
			//timezone change on rpi takes sveral seconds, so it's necessary to send a second restAPI call to the gw.
			setTimeAfterTimezone = true;
			var d = new Date();
			var start = d.getTime();
		} else if((currentYear != yearInput) || (currentMonth != monthInput) || (currentDay != dayInput) || (currentHour != hourInput) || (currentMinute != minutesInput) || (currentSecond != secondsInput)) {

			var gwHour = checkTime(parseInt(hourInput));

			//convert 12h to 24h
			if ($('#timeFormat').val() != "24h") {
				ampm = $(".ampm").val();
				gwHour = convert12to24(gwHour);
			}

			params.utc = yearInput + "-" + checkTime(parseInt(monthInput)) + "-" + checkTime(parseInt(dayInput)) + "T" + gwHour + ":" + checkTime(parseInt(minutesInput)) + ":" + checkTime(parseInt(secondsInput));
		}

		var correctDate = false;
		if ((parseInt(yearInput) > 1970) && (parseInt(yearInput) < 3000) && (parseInt(monthInput) > 0) && (parseInt(monthInput) < 13) && (parseInt(dayInput) > 0) && (parseInt(dayInput) < 32)) {
			correctDate = true;
		}
	} else {
		var correctDate = true;
	}

	if (correctDate == false) {
		showAlert('alert-error', '<b>Error!</b> Date must be in the format: Year - Month - Day', alertid);
	} else {

		currentYear = $('.gwYearInput').val();
		currentMonth = $('.gwMonthInput').val();
		currentDay = $('.gwDayInput').val();
		currentHour = $('.gwHoursInput').val();
		currentMinute = $('.gwMinutesInput').val();
		currentSecond = $('.gwSecondsInput').val();

		$.ajax({
			url: 'api/' + apikey + '/config',
			dataType: 'json',
			type: 'PUT',
			contentType: 'application/json; charset=utf-8',
			headers: { 'Accept': apiversion },
			data: JSON.stringify(params),
			success: function(json) {
				showAlert('alert-success', '<b>OK!</b> Updated configuration.', alertid);
				$('.loading').addClass('hidden');
				if (setTimeAfterTimezone == true) {
					var d = new Date();
					var end = d.getTime();
					var duration = Math.ceil((end - start) / 1000);
					setTime(duration,alertid);
				}
				checkUpdatedData();
			},
			error: function(jqXHR, textStatus, errorThrown) {
				showAlert('alert-error', '<b>Error!</b> Failed to update configuration.', alertid);
			}
		});
	}

}

/**
 * send wifi settings to gateway when user clicks the submit button
 */
function submitWifiSettings(alertid) {

    var params = {};
	var wifiChannel = $('#select-wifi-channel').val();

	if (wifiChannel == 0) { //auto
		wifiChannel = 11; // wifi channel 11 never overlaps with zigbee channels
	}

	if ( !$('.wifi-settings').hasClass('hidden') ) {

		if ( $('#link-client-settings').parent().hasClass('active')) {
			params.wifitype = "client";
			params.wifiname = $('#clientWifiName').html();
			createClient = true;
		} else if ( $('#link-ap-settings').parent().hasClass('active')) {
			params.wifitype = "accesspoint";
			params.wifiname = $('#wifi-name-input').val();
			params.wifichannel = wifiChannel;
			//createAP = true;
		} else {
			params.wifitype = "ad-hoc";
			params.wifiname = $('#wifi-name-input').val();
			params.wifichannel = wifiChannel;
		}
	}

	params.wifi = "running";

	var error = false;
	if ( !$('.wifi-settings').hasClass('hidden') ) {
		var newpw = "";
		if ($('#link-client-settings').parent().hasClass('active')) {
		    // client settings active
			params.wifipassword = $('#newWifiPasswordInput').val();
		} else {
			// AP settings active
			newpw = $('input#wifi-pw-input').val();

			if ($('#wifi-name-input').val() === "") {
				error = true;
				showAlert('alert-error', 'No WiFi name specified!', alertid);
			}

			if (newpw.length < 8) {
				error = true;
				showAlert('alert-error', 'New password must have at least 8 characters!', alertid);
			} else if (newpw.length === 0) {
				error = true;
				showAlert('alert-error', 'New password not specified!', alertid);
			} else {
				params.wifipassword = newpw;
			}
		}

		// AP or client settings active

		if (wifiPwError === true) {
			showAlert('alert-error', 'Invalid characters!', alertid);
		}

	}

	if (error === false && wifiPwError === false) {
		oldWifiName = $('#wifi-name-text').html();
		if ( !$('#clientWifiPasswordModal').hasClass('in') ) {
			showAlert('alert-info', 'Configuring wifi. Please Wait.', alertid);
		}
		$.ajax({
			url: 'api/' + apikey + '/config',
			dataType: 'json',
			type: 'PUT',
			contentType: 'application/json; charset=utf-8',
			headers: { 'Accept': apiversion },
			data: JSON.stringify(params),
			success: function(json) {
				if ( !$('#clientWifiPasswordModal').hasClass('in') ) {
					showAlert('alert-success', '<b>OK!</b> Updated configuration.', alertid);
				}
				var type = (params.wifitype === "accesspoint") ? "Access Point" :
						   (params.wifitype === "ad-hoc") ? "Ad-Hoc" : "Client";
				//$('#wifi-type-text').text(type);
				wifiType = (type === "Access Point") ? WIFI_AP : (type === "Ad-Hoc") ? WIFI_AH : WIFI_CLIENT;
				//$('#wifi-name-text').text(params.wifiname);
				/*
				if (params.wifi === "running") {
					$('#ipAddrRow').removeClass('hidden');

				} else {
					$('#ipAddrRow').addClass('hidden');

				}
				*/
			},
			error: function(jqXHR, textStatus, errorThrown) {
				switch (jqXHR.status) {
					case 502:
						// connected via eth
						$('#ipAddrRow').addClass('hidden');
						$('#wifi-status-row').addClass('hidden');
						//$('#wifi-name-text').text(params.wifiname);
						//if ( !$('#clientWifiPasswordModal').hasClass('in') ) {
							if (params.wifi === "running") {
								if (params.wifitype === "accesspoint") {
									//showAlert('alert-info', 'Wifi configured. The gateway is now restarting. After that it is available at the new wifi-ap under the ip 192.168.8.1', alertid);
									showAlert('alert-info', 'Wifi configured. The gateway is now restarting. Please wait.', alertid);
								} else if (params.wifitype === "ad-hoc") {
									showAlert('alert-info', 'Wifi configured.', alertid);
								} else if (params.wifitype === "client") {
									showAlert('alert-info', '502 Wifi configured. setting up client', alertid);
								}
							}  else {
								//showAlert('alert-info', 'Wifi configured. The gateway is now restarting.', alertid);
								if (params.wifitype === "accesspoint") {
									showAlert('alert-info', '502 Wifi configured. setting up ap NOT RUNNING', alertid);
								} else if (params.wifitype === "ad-hoc") {
									showAlert('alert-info', '502 Wifi configured. setting up ad-hoc NOT RUNNING', alertid);
								} else if (params.wifitype === "client") {
									showAlert('alert-info', '502 Wifi configured. setting up client NOT RUNNING', alertid);
								}
							}
						//}
						break;

					default:
						// connected via wlan
						$('#ipAddrRow').addClass('hidden');
						$('#wifi-status-row').addClass('hidden');
						//$('#wifi-name-text').text(params.wifiname);
						//if ( !$('#clientWifiPasswordModal').hasClass('in') ) {
							if (params.wifi === "running") {
								if (params.wifitype === "accesspoint") {
									//showAlert('alert-info', 'Wifi configured. The gateway is now restarting. After that it is available at the new wifi-ap under the ip 192.168.8.1', alertid);
									showAlert('alert-success', 'WiFi configured. Please connect to the new access point.', alertid);
									setInterval(function(){
										window.location.href = "http://192.168.8.1/edit_system.html";
									},10000);
								} else if (params.wifitype === "ad-hoc") {
									showAlert('alert-info', '0 Wifi configured. setting up ad-hoc', alertid);
								} else if (params.wifitype === "client") {
									showAlert('alert-success', 'Success. WebApp is connecting to new gateway address.', alertid);
									// don't scan, beacuse scan now starts when webapp lost connection
									/*
									scanGatewayState = START_GW_SCAN;
									origin = SETTINGS;
									getIPs(function(ip){
										//local IPs
										if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) {
											networks.push(ip.substring(0, ip.lastIndexOf(".") + 1));
											scanNetworks();
										}
									});
									*/
								}
								$('#connectWifiClientLoading').html('Please wait <img src="img/loading-white.gif"/>');
							}  else {
								//showAlert('alert-info', 'Wifi configured. The gateway is now restarting.', alertid);
								if (params.wifitype === "accesspoint") {
									showAlert('alert-info', '0 Wifi configured. setting up ap NOT RUNNING', alertid);
								} else if (params.wifitype === "ad-hoc") {
									showAlert('alert-info', '0 Wifi configured. setting up ad-hoc NOT RUNNING', alertid);
								} else if (params.wifitype === "client") {
									showAlert('alert-info', '0 Wifi configured. setting up client NOT RUNNING', alertid);
								}
							}
						//}
						break;
				}
			},
			timeout: 10000
		});
	}
}

/**
 * set the gateway date and time
 */
function setTime(dur,alertid) {
	var error = false;
	var sec = parseInt($(".gwSecondsInput").val());
	var min =  parseInt($(".gwMinutesInput").val());
	var hour = parseInt($(".gwHoursInput").val());

	if ((sec + parseInt(dur)) > 59) {
	    sec = dur - (60 - sec);
		min = min + 1;
	} else {
		sec = sec + parseInt(dur);
	}
	if (min > 59) {
		min = 0;
		hour = hour + 1;
	}

	// the only problem is when the user  changes the time a few seconds before midnight
	// then ask the user kindly to try again.
	if ($('#timeFormat').val() == "24h") {
		if (hour > 23) {
			error = true;
		}
	} else {
		if (hour > 12) {
			error = true;
		}
	}

	if (error == false) {

		//convert 12h to 24h
		if ($('#timeFormat').val() != "24h") {
			ampm = $(".ampm").val();
			hour = convert12to24(hour);
		}

		var yearInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwYearInputPhone').value : document.getElementById('gwYearInput').value

		var monthInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwMonthInputPhone').value : document.getElementById('gwMonthInput').value

		var dayInput = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? document.getElementById('gwDayInputPhone').value : document.getElementById('gwDayInput').value

		var utc = yearInput + "-" + checkTime(parseInt(monthInput)) + "-" + checkTime(parseInt(dayInput)) + "T" + checkTime(hour) + ":" + checkTime(min) + ":" + checkTime(sec);

		$.ajax({
			url: 'api/' + apikey + '/config',
			dataType: 'json',
			type: 'PUT',
			contentType: 'application/json; charset=utf-8',
			headers: { 'Accept': apiversion },
			data: '{"utc":"' + utc + '"}',
			success: function(json) {
				showAlert('alert-success', '<b>OK!</b> Updated configuration.',alertid);
				checkUpdatedData();
			},
			error: function(jqXHR, textStatus, errorThrown) {
				showAlert('alert-error', '<b>Error!</b> Failed to update configuration.',alertid);
			}
		});
	} else {
		showAlert('alert-error', '<b>Error!</b> Failed to update time. Please try again to set date and time.',alertid);
	}

}

/**
 * open the network for a given period
 */
function openNetwork(minutes) {

    var params = { "permitjoin" : (parseFloat(minutes)*60) };

    $.ajax({
        url: 'api/' + apikey + '/config',
        dataType: 'json',
        type: 'PUT',
        cache: false,
        contentType: 'application/json; charset=utf-8',
        headers: { 'Accept': apiversion },
        data: JSON.stringify(params),
        success: function(json) {
			if (minutes !== 0) {
				var txt = '<div class="alert alert-info">';
				txt += '<button type="button" class="close" data-dismiss="alert">&times;</button>';
				txt += '<strong>Info!</strong> Network open. Check the <a href="index.html">main page</a> if new Lights where found.';
				txt += '</div>';
				$('#network-open-alert').html(txt);
			} else {
				$('#network-open-alert').html("");
			}
        },
        error: function(jqXHR, textStatus, errorThrown) {
            showAlert('alert-error', '<b>Error!</b> Open Network failed!', '#network-alerts');
        }
    });
}

var updateTimerId;
var updateDots = "";

/**
 * fill the html page with current network settings
 */
function displayNetworkSetting(config) {

    var otauActive = config.config["otauactive"];

    if (otauActive) {
        $('#otauActiveCheckbox').attr('checked', 'checked');
    }
    else {
        $('#otauActiveCheckbox').removeAttr('checked');
    }

	var zigbeechannel = config.config["zigbeechannel"];
	$("#gwChannel").html(zigbeechannel);

		if ((zigbeechannel == 11 ) || (zigbeechannel == 15 ) || (zigbeechannel == 20 ) || (zigbeechannel == 25 )) {
			$("#channelSelect").val(zigbeechannel);
		} else {
			$('#channelSelect')
				.append($("<option></option>")
				.attr("value",zigbeechannel)
				.text(zigbeechannel));
			$("#channelSelect").val(zigbeechannel);
		}

	var networkOpenDuration = config.config["networkopenduration"];

	if (networkOpenDuration != 60 && networkOpenDuration != 600 && networkOpenDuration != 36000) {
		networkOpenDuration = 60;
	}
	$("#networkOpenDuration").val(parseFloat(networkOpenDuration)/60);

	$('.nwOpenText').html('Open the network for '+ parseFloat(networkOpenDuration)/60 + ' ' + ((networkOpenDuration == 60) ? "minute" : "minutes") + ' and allow other ZigBee devices to join the network.');

	currentChannel = $('#channelSelect').val();

	var panId = config.config["panid"];
	var panid = panId.toString(16);
				if (panid.length >= 4) {
					panid = "0x" + panid;
				} else if (panid.length > 2 && panid.length < 4) {
					panid = "0x0" + panid;
				} else if (panid.length > 1 && panid.length < 3) {
					panid = "0x00" + panid;
				} else if (panid.length > 0 && panid.length < 2) {
					panid = "0x000" + panid;
				} else {
					panid = "0x0000";
				}
	$("#gwNetworkId").html(panid);
}

/**
 * fill the html page with current system settings
 */
function displaySetting(config) {

    var swversion = config.config.swversion;

    if (config.config.updatechannel !== 'stable') {
        swversion += ' <span class="label label-info">' + config.config.updatechannel + '</span>';
    }

	var rgbwDisplay = config.config["rgbwdisplay"];
	$("#rgbwDisplay").val(rgbwDisplay);

    $('#gwSwVersion').html(swversion);
	if (Modernizr.sessionstorage) {
		localStorage.setItem("de-gw-swVersion",swversion.substr(0,7));
	}
    $('#gwNameInput').val(config.config.name);

	var year = (config.config.localtime).substr(0,4);
	var month = (config.config.localtime).substr(5, 2);
	var day = (config.config.localtime).substr(8, 2);
	var hour = (config.config.localtime).substr(11, 2);
	var min = (config.config.localtime).substr(14, 2);
	var sec = (config.config.localtime).substr(17, 2);

	var timeFormat = config.config["timeformat"];

	$("#timeFormat").val(timeFormat);

	$('.gwYearInput').val(year);
	$('.gwMonthInput').val(month);
	$('.gwDayInput').val(day);

	if (config.config.timeformat == "24h") {
		$('.gwHoursInput').val(hour);
		$('.ampm').addClass("hidden");
	} else {
		$('.gwHoursInput').val(convert24to12(hour));
		$('.ampm').removeClass("hidden");
		$('.ampm').val(ampm);
	}
	$('.gwMinutesInput').val(min);
	$('.gwSecondsInput').val(sec);

	//$('#gwGroupDelayInput').val(config.config.groupdelay);

    var discovery = config.config.discovery;

    if (discovery === true) {
        $('#internetServiceCheckbox').attr('checked', 'checked');
    }
    else {
        $('#internetServiceCheckbox').removeAttr('checked');
    }

    var curVersion = config.config.swversion;
    var updateVersion = config.config.swupdate.version;

    var updateTxt = "";
    if (compareVersionNumbers(curVersion, updateVersion) === -1)
    {
        updateTxt = '<button class="btn" type="bytton" onclick="updateSoftware(); return false;"><b>update to</b> ' + config.config.swupdate.version + ' </button>';
    }
    else if (config.config.fwneedupdate) {
        updateTxt = '<button class="btn" type="bytton" onclick="updateFirmware(); return false;"><b>update firmware</b></button>';
    }

    $('#gwSwUpdate').html(updateTxt);

	currentYear = $('.gwYearInput').val();
	currentMonth = $('.gwMonthInput').val();
	currentDay = $('.gwDayInput').val();
	currentHour = $('.gwHoursInput').val();
	currentMinute = $('.gwMinutesInput').val();
	currentSecond = $('.gwSecondsInput').val();
}

/**
 * fill the html page with current wifi settings
 */
function displayWifiSetting() {
/*
	if (hidden !== 'undefined') {
        if (document[hidden] === true) {
            setTimeout(displayWifiSetting, POLL_DELAY);
            return;
        }
    }

	$.ajax({
        url: 'api/' + apikey + '/config/wifi',
        type: 'GET',
        cache: false,
        headers: { 'Accept': apiversion },
        success: function(json, textStatus, jqXHR) {
			//var oldWifiName = $('#wifi-name-text').html();

			var type = (json.wifitype === "accesspoint") ? "Access Point" :
					   (json.wifitype === "ad-hoc") ? "Ad-Hoc" : "Client";
			wifiType = (type === "Access Point") ? WIFI_AP : (type === "Ad-Hoc") ? WIFI_AH : WIFI_CLIENT;
			ssid = json.wifiname || '';
			wifiChannel = json.wifichannel;
			wifiPw = json.wifiappw;

			if (!userChangedWifiChannel) {
				if (wifiChannel >= 0 && wifiChannel <= 11) {
					$("#select-wifi-channel").val(wifiChannel);
				} else {
					$('#select-wifi-channel')
						.append($("<option></option>")
						.attr("value",wifiChannel)
						.text(wifiChannel));
					$("#select-wifi-channel").val(wifiChannel);
				}
			}

			if (json.wifi == "running") {
				$('#wifi-type-row').removeClass('hidden');
				$('#wifi-name-row').removeClass('hidden');
				$('#wifi-status-row').removeClass('hidden');
				$('#ipAddrRow').removeClass('hidden');
				$('#restore-wifi-config').removeClass('hidden');
			} else if (json.wifi === "not-configured") {

			} else if (json.wifi === "not-installed") {
				$('#btn-change-wifi').addClass('hidden');
				$('#wifi-not-installed-info').removeClass('hidden');
			}

			$('#wifi-type-text').text(type);
			var name = ssid.replace(/\"/g,"");
			$('#wifi-name-text').text(name);

			if (json.wifitype === "client" && oldWifiName != name && oldWifiName != "") {
			    //connection to client is successfull
				$('#connectWifiClientLoading').addClass("hidden");
				$('#btnChangeWifiPasswordSubmit').addClass("hidden");
				$('#btnChangeWifiPasswordCancel').text("Done");
				showAlert('alert-success', 'Success!', '#connectClientAlert');
			} else if (json.wifitype === "accesspoint" && oldWifiName != name && oldWifiName != "") {
			    //connection to accesspoint is successfull
				showAlert('alert-success', '<b>Success!</b> Accesspoint created.', '#wifi-alerts');
			}

			if (wifiType == WIFI_AP && $('#wifi-pw-input').val() === "" && !$('#wifi-pw-input').is(':focus')) {
				$('#wifi-pw-input').val(wifiPw);
			}

			$('#gw-wifi-addr').text(json.wifiip);
			setTimeout(displayWifiSetting, POLL_DELAY);
        },
        error: function(jqXHR, textStatus, errorThrown) {
			console.log("Error retrieving wifi settings");
			setTimeout(displayWifiSetting, POLL_DELAY);
        }
    });*/
}

$(document).on('change','#select-wifi-channel', function(){
	userChangedWifiChannel = true;
});

/**
 * Start a scan for available wifis
 */
function scanWifis() {
	if (hidden !== 'undefined') {
        if (document[hidden] === true) {
            return;
        }
    }
	$.ajax({
        url: 'api/' + apikey + '/config/wifiscan',
        type: 'POST',
        cache: false,
        headers: { 'Accept': apiversion },
        success: function(json, textStatus, jqXHR) {
			if (jQuery.isEmptyObject(json.cells)) {
				console.log("no wifis found");
				repeatWifiScan = setTimeout(scanWifis, 5000);
			} else {
				updateWifiScanResults(json.cells);
				repeatWifiScan = setTimeout(scanWifis, 10000);
			}
        },
        error: function(jqXHR, textStatus, errorThrown) {
			console.log("Error retrieving wifi settings");
			repeatWifiScan = setTimeout(scanWifis, 5000);
        }
    });
}

/**
 * Update GUI with available wifis
 */
function updateWifiScanResults(cells) {
	if ( ! $('.wifi-settings-client').hasClass('hidden') ) {
		$('#availableWifiText').html("Available Wifi");
		console.log("update wifis");

		var txt = '';

		for (c in cells) {
			var cell = cells[c];
			//make all new
			txt += '<tr>';
			txt += '<td>' + cell.name + '</td>';
			txt += '<td>' + cell.channel + '</td>'
			txt += '<td>' + cell.security + '</td>'
			txt += '<td>' + convertSignalStrength(cell.signalstrength) + '</td>'
			txt += '<td><button class="btn btn-primary connectToWifiBtn" id="' + cell.name + '">Connect</button></td>'
			txt += '</tr>';
		}
		$('#availableWifiTable').html("");
		$('#availableWifiTable').html(txt);
	}
}

$(document).on('click','.connectToWifiBtn',function() {
	$('#clientWifiPasswordModal').modal({ backdrop: 'static' });
	$('#clientWifiName').html(this.id);
	if ($('#clientWifiName').html() == "") {
		$('#clientWifiName').html($('#customWifiName').val());
	}
	$('#newWifiPasswordInput').focus();
});

$(document).on('hide','#clientWifiPasswordModal',function() {
	$('#connectClientAlert').html("");
	$('#connectWifiClientLoading').addClass("hidden");
	$('#newWifiPasswordInput').val("");
	$('#btnChangeWifiPasswordSubmit').removeClass("hidden");
	$('#btnChangeWifiPasswordCancel').text("Cancel");
});

/**
 * Show enter wifi password modal
 */
function connectToWifi(wifiName) {
	if ( !$('.wifi-settings').hasClass('hidden') && $('#link-client-settings').parent().hasClass('active') ) {
		if ( ($('#newWifiPasswordInput').val() === "") ) {
			showAlert('alert-error', 'No Password specified!', '#connectClientAlert');
		} else {
			$('#connectWifiClientLoading').removeClass('hidden');
			submitWifiSettings('#connectClientAlert');
		}
	}
}

/**
 * Convert dB signal strength to human readable values
 */
function convertSignalStrength(value) {
	var db = parseInt(value);
	result = "";

	if (db > -50) {
		result = '<img src="img/wifi4.png" alt="super" />';
	} else if (db > -70 && db <= -50) {
		result = '<img src="img/wifi3.png" alt="good" />';
	} else if (db > -90 && db <= -70) {
		result = '<img src="img/wifi2.png" alt="medium" />';
	} else if (db <= -90) {
		result = '<img src="img/wifi1.png" alt="bad" />';
	}

	return result;
}

/**
 * Poll the gateway for connectivity to inform the user
 * when the update is done.
 */
function pollUpdateReady() {
    $.ajax({
        url: 'api/' + apikey + '/config',
        type: 'GET',
        cache: false,
        headers: { 'Accept': apiversion },
        success: function(json, textStatus, jqXHR) {
            showAlert('alert-success', '<b>OK!</b> Software update done.', '#system-alerts');
            updateTimerId = undefined;
            //getFullConfiguration();
			window.location.reload();
        },
        error: function(jqXHR, textStatus, errorThrown) {
            switch (jqXHR.status) {
            case 403:
                window.location.assign("/pwa/login.html");
                break;

            default:
                updateDots += ' .';
                showAlert('alert-info', '<b>Updating!</b> Please wait and don\'t close this page the update may take up to several minutes.' + updateDots, '#system-alerts');
                updateTimerId = setTimeout(pollUpdateReady, 5000);
                break;
            }
        }
    });
}

/**
 * Send request to update the software via the selected update channel.
 */
function updateSoftware() {
    if (updateTimerId) {
        clearTimeout(updateTimerId);
        updateTimerId = undefined;
    }

    updateDots = "";

    $.ajax({
        url: 'api/' + apikey + '/config/update',
        type: 'POST',
        cache: false,
        headers: { 'Accept': apiversion },
        success: function(json) {
            showAlert('alert-info', '<b>Updating!</b> Please wait and don\'t close this page the update may take up to several minutes.', '#system-alerts');
            updateTimerId = setTimeout(pollUpdateReady, 8000);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            showAlert('alert-error', '<b>Error!</b> Software update failed, please try again later.', '#system-alerts');
        }
    });
}

/**
 * Send request to update the firmware.
 */
function updateFirmware() {
    if (updateTimerId) {
        clearTimeout(updateTimerId);
        updateTimerId = undefined;
    }

    updateDots = "";

    $.ajax({
        url: 'api/' + apikey + '/config/updatefirmware',
        type: 'POST',
        cache: false,
        headers: { 'Accept': apiversion },
        success: function(json) {
            showAlert('alert-info', '<b>Updating!</b> Please wait, the update may take up to several minutes.', '#system-alerts');
        },
        error: function(jqXHR, textStatus, errorThrown) {
            showAlert('alert-error', '<b>Error!</b> Firmware update failed, please try again later.', '#system-alerts');
        }
    });
}

/**
 * GET api/<apikey>
 */
function getFullConfiguration() {

    $.ajax({
        url: 'api/' + apikey,
        dataType: 'json',
        type: 'GET',
        cache: false,
        contentType: 'application/json; charset=utf-8',
        headers: { 'Accept': apiversion },
        success: function(json, status, xhr) {
			//stop gw scanning
			scanGatewayState = STOP_GW_SCAN;

            clearAlert();
			clearAlert('#wifi-alerts');
            displaySetting(json);
			displayNetworkSetting(json);
			//displayWifiSetting();

			config = json;
            config.etag = xhr.getResponseHeader("ETag");

			checkNetworkOpenWarning();

			if (config.config.system != "linux-gw") {
				// hide time settings on windows
				$('.gateway-date').html("");
				$('.gateway-time').html("");
				$('.gateway-timezone').html("");
				// hide wifi on windows
				$('#wifiHeadline').html("");
				$('#wifiHeadline').removeClass("page-header");
				$('#wifiTable').html("");
				$('.wifi-apply-btn').html("");
			} else {
				//fill timezoneselect with timezones
				$('.timezoneselect').timezones();
				currentTimezone = config.config.timezone;
				// show backup only for Raspberry
				$('.backup-sys').removeClass('hidden');
			}

			// show/hide features based on update channel
			$('[data-channel]').each(function(){
				if ($(this).attr('data-channel').indexOf(config.config.updatechannel) != -1 &&
				    (!$(this).hasClass("advanced-sys") && !$(this).hasClass("advanced-nw"))) {
					$(this).removeClass('hidden');
				}
			});

            // make available for caching
            if (Modernizr.sessionstorage) {
                sessionStorage.config = xhr.responseText;
            }

            setTimeout(checkUpdatedData, POLL_DELAY);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            switch (jqXHR.status) {
            case 403:
                window.location.assign("/pwa/login.html");
                break;

            default:
				if (config.config.updatechannel === "alpha") {
					//if ((config.config.wifi == "running" && config.config.wifitype == "client") || createClient) {
						showAlert('alert-warning', '<b>Lost connection!</b> Trying to reconnect.');
						if (scanGatewayState == STOP_GW_SCAN) {
							scanGatewayState = START_GW_SCAN;
							origin = SETTINGS;
							getIPs(function(ip){
								//local IPs
								if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) {
									networks.push(ip.substring(0, ip.lastIndexOf(".") + 1));
									scanNetworks();
								}
							});
						}
					//}
				}
                setTimeout(getFullConfiguration, 1000);
                break;
            }
        },
        timeout: 3000
    });

}

/**
 * unlock gateway for 3rd party apps
 */
function unlockGateway(seconds) {

    var params = { "unlock" : seconds };

    clearAlert();

    $.ajax({
        url: 'api/' + apikey + '/config',
        dataType: 'json',
        type: 'PUT',
        cache: false,
        contentType: 'application/json; charset=utf-8',
        headers: { 'Accept': apiversion },
        data: JSON.stringify(params),
        success: function(json) {
            showAlert('alert-success', '<b>OK!</b> Unlocked gateway for ' + seconds + ' seconds.', '#system-alerts');
			setTimeout(function(){clearAlert('#system-alerts')},60000);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            showAlert('alert-error', '<b>Error!</b> Unlock gateway failed!', '#system-alerts');
        }
    });
}

/**
 * displays change password alert
 */
function showChangePasswordAlert(alert, text) {
    var txt = "";

    txt += '<div class="alert ' + alert + '">';
    txt += text;
    txt += '</div>';

    $('#changePasswordAlert').html(txt);
}

$('#changePasswordModal').on('show', function () {
    // clear alert
    $('#oldPasswordInput').val("");
    $('#newPasswordInput').val("");
    $('#confirmPasswordInput').val("");
    $('#changePasswordAlert').html("");
})

/**
 * api/<apikey>/config/password
 */
function sendChangePassword() {
    clearAlert();
    var oldpw = $('#oldPasswordInput').val();
    var newpw = $('#newPasswordInput').val();
    var confpw = $('#confirmPasswordInput').val();

    if (oldpw.length === 0) {
        showChangePasswordAlert('alert-error', 'Old password not specified!')
    }
    else if (newpw.length < 5) {
        showChangePasswordAlert('alert-error', 'New password must have at least 5 characters!')
    }
    else if (newpw.length === 0) {
        showChangePasswordAlert('alert-error', 'New password not specified!')
    }
    else if (newpw !== confpw) {
        showChangePasswordAlert('alert-error', 'New and confirm password differ!')
    }
    else {
        $('#changePasswordModal').modal('hide');

        var username = "delight"; // fixed
        // combine and base64 encode username:password as in HTTP basic authentification
        var oldhash = Base64.encode(username + ':' + oldpw);
        var newhash = Base64.encode(username + ':' + newpw);

        var params = {
            "username": username,
            "oldhash": oldhash,
            "newhash": newhash
        };

        $.ajax({
            url: 'api/' + apikey + '/config/password',
            dataType: 'json',
            type: 'PUT',
            contentType: 'application/json; charset=utf-8',
            headers: { 'Accept': apiversion },
            //processData: false,
            data: JSON.stringify(params),
            success: function(json) {
                showAlert('alert-success', '<b>OK!</b> Changed password.');
            },
            error: function(jqXHR, textStatus, errorThrown) {
                if (jqXHR.status === 401) {
                    showAlert('alert-error', '<b>Error!</b> Changing password failed, old password wrong!', '#system-alerts');
                }
                else {
                   showAlert('alert-error', '<b>Error!</b> Changing password failed!', '#system-alerts');
                }
            }
        });
    }
}

/**
 * check the wifi password input for unsupported chatacters
 */
$(document).on('input','#wifi-pw-input',function(){
	checkPasswordCharacters($('#wifi-pw-input').val());
});

function checkPasswordCharacters(password) {
	var invalidChars = "";
	wifiPwError = false;
	/*
	for (c in unsupportedChars) {
		if (password.indexOf(unsupportedChars[c]) != -1) {
			invalidChars += unsupportedChars[c];
			wifiPwError = true;
		}
	}
	*/

	if (password.length != 0 && !validChars.test(password)) {
			//invalidChars += password.substr(password.length-1,1);
			wifiPwError = true;
		}

	if (wifiPwError === true) {
		$('#wifi-pw-input').css('background-color','#ffcccc');
		$('#wifi-pw-input').css('box-shadow','0px 0px 10px 0px rgba(255,50,50,1)');
		$('#wrongPasswordInfo').text("Invalid characters");
	} else {
		$('#wifi-pw-input').css('background-color','#fff');
		$('#wifi-pw-input').css('box-shadow','none');
		if (password.length < 8) {
			$('#wrongPasswordInfo').text("Password is to short");
		} else {
			$('#wrongPasswordInfo').html('<span style="color:#09ec09;">Password Ok</span>');
		}
	}
}

/**
 * PUT api/<apikey>/config/wifi/restore
 */
function sendRestoreWifi() {
    clearAlert();
	$('#restore-wifi-modal').modal('hide');
	showAlert('alert-info', '<b>OK!</b> Deactivating WiFi. Please wait.', '#wifi-alerts');
	$.ajax({
		url: 'api/' + apikey + '/config/wifi/restore',
		dataType: 'json',
		type: 'PUT',
		contentType: 'application/json; charset=utf-8',
		headers: { 'Accept': apiversion },
		success: function(json) {
		},
		error: function(jqXHR, textStatus, errorThrown) {
			if (jqXHR.status == 502 || textStatus == "timeout") {
				showAlert('alert-success', '<b>OK!</b> WiFi Deactivated. The gateway will be available in a few seconds.', '#wifi-alerts');
			} else {
				showAlert('alert-error', '<b>Error!</b> Restoring original configuration failed!', '#wifi-alerts');
			}
		}
	});
}

/**
 * Displays or hides the network is open warning.
 */
function checkUpdatedData() {
    if (hidden !== 'undefined') {
        if (document[hidden] === true) {
            console.log('don\'t update while browser window is hidden');
            setTimeout(checkUpdatedData, POLL_DELAY);
            return;
        }
    }

    $.ajax({
        url: 'api/' + apikey,
        dataType: 'json',
        type: 'GET',
        cache: false,
        contentType: 'application/json; charset=utf-8',
        headers: {
            'If-None-Match': config.etag,
            'Accept': apiversion
        },
        success: function(json, status, xhr) {
			//stop gw scanning
			scanGatewayState = STOP_GW_SCAN;

            clearAlert();
            if (xhr.status === 304) {
                // call self
                setTimeout(checkUpdatedData, POLL_DELAY);
                return;
            }

            var fwupdatestate = config.config.fwupdatestate; // 'old' state

            // always copy permit join
            config.config.permitjoin = json.config.permitjoin;
            config = json;


            var updateTxt = "";
            if (config.config.fwupdatestate === "running") {
                showAlert('alert-info', '<b>Updating!</b> Please wait, the update may take up to several minutes.' + updateDots, '#system-alerts');

            } else if (config.config.fwupdatestate !== fwupdatestate) { // transition
                clearAlert('#system-alerts');
            }

            if (config.config.fwupdatestate === "idle") {
                var curVersion = config.config.swversion;
                var updateVersion = config.config.swupdate.version;

                if (compareVersionNumbers(curVersion, updateVersion) === -1)
                {
                    updateTxt = '<button class="btn" type="bytton" onclick="updateSoftware(); return false;"><b>update to</b> ' + config.config.swupdate.version + ' </button>';
                }
                else if (config.config.fwneedupdate) {
                    updateTxt = '<button class="btn" type="bytton" onclick="updateFirmware(); return false;"><b>update firmware</b></button>';
                }
            }
            $('#gwSwUpdate').html(updateTxt);

			// make available for caching
			if (Modernizr.sessionstorage) {
				sessionStorage.config = xhr.responseText;
			}

            checkNetworkOpenWarning();

            config.etag = xhr.getResponseHeader("ETag");
            if (!config.etag) {
                config.etag = "";
            }

            // call self
            setTimeout(checkUpdatedData, POLL_DELAY);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            if (jqXHR.status == 0 || textStatus == "timeout") {
				if (config.config.updatechannel === "alpha") {
					//if ((config.config.wifi == "running" && config.config.wifitype == "client") || createClient) {
						showAlert('alert-warning', '<b>Lost connection!</b> Trying to reconnect.');
							// try from beginning on (also to clear the alert box on success)
							if (scanGatewayState == STOP_GW_SCAN) {
								scanGatewayState = START_GW_SCAN;
								origin = SETTINGS;
								getIPs(function(ip){
									//local IPs
									if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) {
										networks.push(ip.substring(0, ip.lastIndexOf(".") + 1));
										scanNetworks();
									}
								});
							}
					//}
				}
				setTimeout(checkUpdatedData, 3000);
				return;
			}
            switch (jqXHR.status) {
            case 403:
                window.location.assign("/pwa/login.html");
                break;

            default:
				if (config.config.updatechannel === "alpha") {
					//if ((config.config.wifi == "running" && config.config.wifitype == "client") || createClient) {
						showAlert('alert-warning', '<b>Lost connection!</b> Trying to reconnect.');
							if (scanGatewayState == STOP_GW_SCAN) {
								scanGatewayState = START_GW_SCAN;
								origin = SETTINGS;
								getIPs(function(ip){
									//local IPs
									if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) {
										networks.push(ip.substring(0, ip.lastIndexOf(".") + 1));
										scanNetworks();
									}
								});
							}
					//}
				}
                setTimeout(checkUpdatedData, 3000);
                break;
            }
        },
        timeout: 10000
    });
}

/**
 * Displays message if network is currently open
 */
function checkNetworkOpenWarning() {
	var timeText = (config.config.permitjoinfull >= 60) ? ((parseInt(config.config.permitjoinfull) / 60) + 1) + " minutes" : config.config.permitjoin + " seconds";
	if ($.trim($('#network-open-alert').html()).length) {
        // case 1 remove warning
        if (config.config.permitjoinfull === 0 && config.config.permitjoin === 0) {
			//$('#no-lights-info').removeClass('hidden');
            $('#network-open-alert').html("");
			$('#btn-open-network').text("Open Network");
            return;
        }

        // case 2 warning already visible, update
		if (config.config.permitjoinfull > 0 || config.config.permitjoin > 0) {
			var txt = '<div class="alert alert-info">';
			txt += '<strong>Info!</strong> Network open. Check the <a href="index.html">main page</a> if new Lights where found. '+ timeText +' left';
			txt += '</div>';
			$('#network-open-alert').html(txt);
			return;
		}
    }

    // case 3 display warning
    if (config.config.permitjoinfull > 0 || config.config.permitjoin > 0) {
	    $('#no-lights-info').addClass('hidden');
        var txt = '<div class="alert alert-info">';
        txt += '<strong>Info!</strong> Network open. Check the <a href="index.html">main page</a> if new Lights where found. '+ timeText +' left';
        txt += '</div>';
        $('#network-open-alert').html(txt);
		$('#btn-open-network').text('Close Network');
    }
}

function checkTime(i) {
    if (i<10) {i = "0" + i};  // add zero in front of numbers < 10
    return i;
}

/**
 * convert 24h hour to 12h format
 */
function convert24to12(hour) {
	var curHour12;

	if (hour == "12") {
		curHour12 = "12";
		ampm = "pm";
	} else if (hour == "00") {
		curHour12 = "12";
		ampm = "am";
	} else if ((parseInt(hour) > 12) && (parseInt(hour) < 24)) {
		curHour12 = parseInt(hour) - 12;
		if ((curHour12 > 0) && (curHour12 < 10)) {
			curHour12 = "0" + curHour12;
		}
		ampm = "pm";
	} else if ((parseInt(hour) > 0) && (parseInt(hour) < 12)) {
		curHour12 = hour;
		ampm = "am";
	}
	return curHour12;
}

/**
 * convert 12h hour to 24h format
 */
function convert12to24(h) {
	var curHour24;

	if ((h == "12") && (ampm == "pm")) {
		curHour24 = "12";
	} else if ((h == "12") && (ampm == "am")) {
		curHour24 = "00";
	} else if ((parseInt(h) > 0) && (parseInt(h) < 12) && (ampm == "am")) {
		curHour24 = h;
	} else if ((parseInt(h) > 0) && (parseInt(h) < 12) && (ampm == "pm")) {
		curHour24 = parseInt(h) + 12;
	}
	return curHour24;
}

/**
 * checks if the given time is a valid input
 */
function checkCorrectTime() {
    var maxHour = ($('#timeFormat').val() == "24h") ? 23 : 12;
    var minHour = ($('#timeFormat').val() == "24h") ? 0 : 1;
	var result = true;

    if ((parseInt($('.gwHoursInput').val()) < minHour) || (parseInt($('.gwHoursInput').val()) > maxHour)) {
		showAlert('alert-error', '<b>Error!</b> Hour must be between ' + minHour + ' and ' + maxHour, '#system-alerts');
		result = false;
    }
	if ((parseInt($('.gwMinutesInput').val()) < 0) || (parseInt($('.gwMinutesInput').val()) > 59)) {
		showAlert('alert-error', '<b>Error!</b> Minutes must be between 0 and 59', '#system-alerts');
		result = false;
    }
	if ((parseInt($('.gwSecondsInput').val()) < 0) || (parseInt($('.gwSecondsInput').val()) > 59)) {
		showAlert('alert-error', '<b>Error!</b> Seconds must be between 0 and 59', '#system-alerts');
		result = false;
    }
	return result;
}

/**
 * Get the actual local date and time from Client and set it as Gateway date and time.
 */
function setCurrentDate() {
	var smallDevice = (window.matchMedia("(max-width: " + SMALL_DEVICE_480 + "px)").matches == true) ? true : false;

	var date = new Date();
	var year = date.getFullYear();
	var month = ((date.getMonth()+1) < 10) ? "0" + (date.getMonth()+1) : (date.getMonth()+1);
	var day = (date.getDate() < 10) ? "0" + date.getDate() : date.getDate();
	var hour = (date.getHours() < 10) ? "0" + date.getHours() : date.getHours();
	var min = (date.getMinutes() < 10) ? "0" + date.getMinutes() : date.getMinutes();
	var sec = (date.getSeconds() < 10) ? "0" + date.getSeconds() : date.getSeconds();

	if (smallDevice === true) {
		$('#gwYearInputPhone').val(year);
		$('#gwMonthInputPhone').val(month);
		$('#gwDayInputPhone').val(day);
		if ($('#timeFormat').val() != "24h") {
			ampm = $(".ampm").val();
			$('#gwHoursInputPhone').val(convert24to12(hour));
		} else {
			$('#gwHoursInputPhone').val(hour);
		}
		$('#gwMinutesInputPhone').val(min);
		$('#gwSecondsInputPhone').val(sec);
	} else {
		$('#gwYearInput').val(year);
		$('#gwMonthInput').val(month);
		$('#gwDayInput').val(day);
		if ($('#timeFormat').val() != "24h") {
			ampm = $(".ampm").val();
			$('#gwHoursInput').val(convert24to12(hour));
		} else {
			$('#gwHoursInput').val(hour);
		}
		$('#gwMinutesInput').val(min);
		$('#gwSecondsInput').val(sec);
	}

	setTimeout(function(){
		setCurrentDate();
	},1000);
}

function clearLocalStorageKeys() {
	if (config != undefined) {
		// clear whitebar hidden status
		for (var key in localStorage) {
			if (key.indexOf("whitebar-") != -1) {
				localStorage.removeItem(key);
			}
		}
		// clear whitebar hidden status of groups
		var groupIds = [];
		for (var key in localStorage) {
			if (key.indexOf("whitebarGroup-") != -1) {
				localStorage.removeItem(key);
			}
			// clear visible status
			if (key.indexOf("visible-") != -1) {
				localStorage.removeItem(key);
			}
			// clear lights sequence
			if (key.indexOf("lightssequence-") != -1) {
				localStorage.removeItem(key);
			}
			// clear groupsequence
			if (key.indexOf("groupssequenceleft") != -1) {
				localStorage.removeItem(key);
			}
			if (key.indexOf("groupssequenceright") != -1) {
				localStorage.removeItem(key);
			}
		}
	}
}
