var STOP_GW_SCAN = 0;
var START_GW_SCAN = 1;
var scanGatewayState = STOP_GW_SCAN;

var scanning = false;
var networks = [];
var scanAttempts = 0;
var MAX_SCAN_ATTEMPTS = 10;
var SRF = [100,1,31,141];
var SRT = [140,30,99,255];
var STO = [120,130,150];
var SCAN_RANGE_FROM = SRF[0]; // 110..0
var SCAN_RANGE_TO = SRT[0];   // 135..255
var SCAN_TIMEOUT = STO[0];    // 100 .. 500


//origin sites before app lost connection
var LIGHT_CONTROL = 0;
var EDIT_GROUPS = 1;
var EDIT_GROUP_MEMBERS = 2;
var EDIT_SCENES = 3;
var SCHEDULES = 4;
var DEVICES = 5;
var SETTINGS = 6;
var origin = SETTINGS;

function getIPs(callback){
	var ip_dups = {};

	//compatibility for firefox and chrome
	var RTCPeerConnection = window.RTCPeerConnection
		|| window.mozRTCPeerConnection
		|| window.webkitRTCPeerConnection;
	var useWebKit = !!window.webkitRTCPeerConnection;

	//bypass native webrtc blocking using an iframe
	if(!RTCPeerConnection){
		//NOTE: you need to have an iframe in the page right above the script tag
		//
		//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
		//<script>...getIPs called in here...
		//
		var win = iframe.contentWindow;
		RTCPeerConnection = win.RTCPeerConnection
			|| win.mozRTCPeerConnection
			|| win.webkitRTCPeerConnection;
		useWebKit = !!win.webkitRTCPeerConnection;
	}

	//minimal requirements for data connection
	var mediaConstraints = {
		optional: [{RtpDataChannels: true}]
	};

//                var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
	var servers = null;

	//construct a new RTCPeerConnection
	var pc = new RTCPeerConnection(servers, mediaConstraints);

	function handleCandidate(candidate){
		//match just the IP address
		var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
		var ip_addr = ip_regex.exec(candidate)[1];

		//remove duplicates
		if(ip_dups[ip_addr] === undefined)
			callback(ip_addr);

		ip_dups[ip_addr] = true;
	}

	//listen for candidate events
	pc.onicecandidate = function(ice){

		//skip non-candidate events
		if(ice.candidate)
			handleCandidate(ice.candidate.candidate);
	};

	//create a bogus data channel
	pc.createDataChannel("");

	//create an offer sdp
	pc.createOffer(function(result){

		//trigger the stun server request
		pc.setLocalDescription(result, function(){}, function(){});

	}, function(){});

	//wait for a while to let everything done
	setTimeout(function(){
		//read candidate info from local description
		var lines = pc.localDescription.sdp.split('\n');

		lines.forEach(function(line){
			if(line.indexOf('a=candidate:') === 0)
				handleCandidate(line);
		});
	}, 1000);
}

function scanNetworks() {
	if (scanning || scanGatewayState == STOP_GW_SCAN)
		return;

	if (networks.length === 0) {
		console.log("finished scanning");
		$('#scanState').text("finished scanning");
		// scan again
		if (scanAttempts <= MAX_SCAN_ATTEMPTS) {
			scanAttempts++;
			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));
					
					//incremental adaption of scaning range and timeout					
					/*
					if (SCAN_RANGE_FROM > 0) {
						SCAN_RANGE_FROM -= 10;	
					}
					if (SCAN_RANGE_TO < 255) {
						SCAN_RANGE_TO += 10;
					}
					if (SCAN_TIMEOUT < 500) {
						SCAN_TIMEOUT += 10;
					}
					if (SCAN_TIMEOUT >= 200) {
						SCAN_TIMEOUT = 120;
					}
					*/
					
					switch (SCAN_RANGE_FROM) {
						case SRF[0]:
							if (SCAN_TIMEOUT == STO[0]) {
								SCAN_TIMEOUT = STO[1];
							} else if (SCAN_TIMEOUT == STO[1]) {
								SCAN_TIMEOUT = STO[2];
							} else {
								SCAN_RANGE_FROM = SRF[1];
								SCAN_RANGE_TO = SRT[1];
								SCAN_TIMEOUT = STO[0];
							}
							break;
						case SRF[1]:
							if (SCAN_TIMEOUT == STO[0]) {
								SCAN_TIMEOUT = STO[1];
							} else if (SCAN_TIMEOUT == STO[1]) {
								SCAN_TIMEOUT = STO[2];
							} else {
								SCAN_RANGE_FROM = SRF[2];
								SCAN_RANGE_TO = SRT[2];
								SCAN_TIMEOUT = STO[0];
							}
							break;
						case SRF[2]:
							if (SCAN_TIMEOUT == STO[0]) {
								SCAN_TIMEOUT = STO[1];
							} else if (SCAN_TIMEOUT == STO[1]) {
								SCAN_TIMEOUT = STO[2];
							} else {
								SCAN_RANGE_FROM = SRF[3];
								SCAN_RANGE_TO = SRT[3];
								SCAN_TIMEOUT = STO[0];
							}
							break;	
						case SRF[3]:
							if (SCAN_TIMEOUT == STO[0]) {
								SCAN_TIMEOUT = STO[1];
							} else if (SCAN_TIMEOUT == STO[1]) {
								SCAN_TIMEOUT = STO[2];
							} else {
								SCAN_RANGE_FROM = SRF[0];
								SCAN_RANGE_TO = SRT[0];
								SCAN_TIMEOUT = STO[0];
							}
							break;	
					}
					
					scanNetworks();
				} else {
					SCAN_RANGE_FROM = SRF[0];
					SCAN_RANGE_TO = SRT[0];
					SCAN_TIMEOUT = STO[0];
					scanAttempts = 0;
					setTimeout(scanNetworks, 1000);
				}
			});
		} else {
			scanGatewayState = STOP_GW_SCAN;
			// return back to accesspoint mode
			$.ajax({
			url: 'api/' + apikey + '/config',
			dataType: 'json',
			type: 'PUT',
			cache: false,
			contentType: 'application/json; charset=utf-8',
			headers: { 'Accept': apiversion },
			data: '{"wifi":"running","wifitype":"accesspoint","wifiname":"RaspBee-AP","wifichannel":1,"wifipassword":"raspbeegw"}',
			success: function(json) {
				showAlert('alert-warning', 'Connection to WiFi not possible. Restoring access point.', '#wifi-alerts');
			},
			error: function(jqXHR, textStatus, errorThrown) {
				showAlert('alert-error', 'Connection to WiFi not possible. Restoring access point.', '#wifi-alerts');			
			}
		});
		}
		return;
	}

	var net = networks.shift()
	scan(net, SCAN_RANGE_FROM);
}

function scan(ipprefix, host) {
	if (scanGatewayState == STOP_GW_SCAN)
		return;
		
	var apikey = localStorage.getItem("apikey");
	if (host >= SCAN_RANGE_TO) {
		scanNetworks();
		return;
	}

	console.log("scan " + ipprefix + String(host) + " " + apikey);
	scanning = true;

	$('#scanState').text("scan from: " + SCAN_RANGE_FROM + " to: " + SCAN_RANGE_TO + ", timeout: " + SCAN_TIMEOUT);
	$('#scanState2').text("scan " + ipprefix + String(host));

	$.ajax({
		type: "GET",
		url: "http://" + ipprefix + String(host) + "/api/" + apikey + "/config",
		crossDomain : true,
		cache: false,
		timeout: SCAN_TIMEOUT
	 })
	.done(function( data ) {
		console.log("Found Gateway: " + ipprefix + String(host));
		scanning = false;
		//scan(ipprefix, host + 1);
		if (origin == LIGHT_CONTROL) {
			window.location.href = "http://" + ipprefix + String(host);
		} else {
			window.location.href = "http://" + ipprefix + String(host) + "/edit_system.html";
		}
	})
	.fail( function(xhr, textStatus, errorThrown) {
		scanning = false;
		setTimeout(function(){
			scan(ipprefix, host + 1);
		},10);
	});
}