// Copyright 2009, Acknack Ltd. All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.





//---------------------------------------------------------------------
//Global Varialbes
//---------------------------------------------------------------------
var F = function() {
    var globals = { "FB_CONNECT_ORIGIN" : "http://gadget.wave.to",
    				"FB_CONNECT_FRAME_SRC" : "http://gadget.wave.to/iWave/FBC.htm",
    				"REQUEST_DELAY" : 100,
    				"FIELDS" : ["name", "comment", "gender", "age", "location", "country", "email", "twitter"]
    				}
    return { get : function(s) {
                return globals[s];
        	},
        	create : function(nam, val) {
    			if(globals[nam] == undefined) {
    				globals[nam] = val;
    			}
    		}
    }
}();





//---------------------------------------------------------------------
//Google I/O
//---------------------------------------------------------------------

//Used for IO with google
var waveIO = function(){
	var delta = {};
	var cache = {};
	return {
		append: function(key, dat){
			delta[key] = dat;
			cache[key] = dat;
		},
		flush: function (){
			wave.getState().submitDelta(delta);
			delta = {};
			cache = {};
		},
		get: function(key) {
			if(cache[key] == undefined) {
				cache[key] = wave.getState().get(key);
			}
			return cache[key];
		},
		forceFlush: function() {
			//Sends the date value to force wave to refresh the values on all ends
			var d = new Date()
			delta["@force"] = d.getTime();
			wave.getState().submitDelta(delta);
			delta = {};
			cache = {};
		}
	};
}();






//---------------------------------------------------------------------
//Google req. methods
//---------------------------------------------------------------------
 	
//Initialization
function init() {
	//Place the frame on the page and start the pinging procedure
	var fbConnectFrame = document.body.appendChild(createIframe("fbConnectFrame", F.get("FB_CONNECT_FRAME_SRC"), 500, 500));
	F.create("FB_CONNECT_WINDOW", fbConnectFrame.contentWindow);
	pingiFrame();
	
	if (wave && wave.isInWaveContainer()) {
		wave.setStateCallback(stateUpdated);
	}
}

gadgets.util.registerOnLoadHandler(init);


//Called when the gadget state is updated
function stateUpdated() {
	//Not yet connected
	if(F.get("CONNECTED") == undefined) {
		setTimeout('stateUpdated()', F.get("REQUEST_DELAY"));
	} else {
		//Tell FBC to render either the host or client
		renderProfilePage();
	}
}
	
	
	
	


//---------------------------------------------------------------------
//iFrame Listener
//---------------------------------------------------------------------	

//Message passing for facebook connect
function receiveMessage(event) {
	if(event.origin === F.get("FB_CONNECT_ORIGIN")) {
		//No connection
		if(F.get("CONNECTED") == undefined) {
			if(event.data === "[ping]") {
				F.create("CONNECTED", true);
			}
		}
		//Connected
		else {
			var identifier = event.data.split("|")[0];
			var key = identifier.split("]")[0].split("[")[1];
			var val = identifier.split("}")[0].split("{")[1];
			
			if(key === "command") {
				if(val === "edit") {
					var message = "[command]{edit}" + bundleVariables();
					F.get("FB_CONNECT_WINDOW").postMessage(message, F.get("FB_CONNECT_ORIGIN"));
				} else if(val === "cancel") {
					renderProfilePage();
				} else if(val === "save") {
					processIncomingVariables(event.data);
					renderProfilePage();
				} else if(val === "update") {
					processIncomingVariables(event.data);
					renderProfilePage();
				}
			}
		}
		
		
		
		
	}
}
window.addEventListener("message", receiveMessage, false);











//---------------------------------------------------------------------
//Support methods
//---------------------------------------------------------------------	


//Creates an iFrame with the given attributes
function createIframe(id, srce, h, w) {
	var newElem = document.createElement("iframe");
	newElem.setAttribute("id", id);
	newElem.setAttribute("src", srce);
	newElem.setAttribute("height", h);
	newElem.setAttribute("width", w);
	newElem.setAttribute("frameborder", 0);
	return newElem;
}

//Keep pinging the frame to ensure it is alive
function pingiFrame() {
	if(F.get("CONNECTED") == undefined) {
		F.get("FB_CONNECT_WINDOW").postMessage("[ping]", F.get("FB_CONNECT_ORIGIN"));
		setTimeout('pingiFrame()', F.get("REQUEST_DELAY"));
	} else {
		F.get("FB_CONNECT_WINDOW").postMessage("[command]{fbconnect}|[ishost]{"+ isHost() +"}", F.get("FB_CONNECT_ORIGIN"));
	}
}

//Return true if the current user is the host
function isHost() {
	if(wave.getHost().getId() === wave.getViewer().getId()) {
		return true;
	} else {
		return false;
	}
}

//Send a render command to FBC
function renderProfilePage() {
	waveIO.flush();
	var message = "";
	if(isHost()) {
		message = "[render]{host}";
	} else {
		message = "[render]{viewer}";
	}
	//Bundle the variables up ready for transmission
	message = message + bundleVariables();
	F.get("FB_CONNECT_WINDOW").postMessage(message, F.get("FB_CONNECT_ORIGIN"));
}

//Place all the variables in a constructed string for transmission
function bundleVariables() {
	var message = "";
	for(var i = 0; i < F.get("FIELDS").length; i++) {
		var temp = F.get("FIELDS")[i];
		if(waveIO.get(temp) != undefined) {
			message = message + "|[" + temp + "]{" + waveIO.get(temp) + "}";
		}
	}
	if(waveIO.get("photo") != undefined) {
		message = message + "|[photo]{" + waveIO.get("photo") + "}";
	}
	if(waveIO.get("facebook") != undefined) {
		message = message + "|[facebook]{" + waveIO.get("facebook") + "}";
	}
	message = message + "|[hostAddress]{" + wave.getHost().getId() + "}";
	return message;
}

//Deconstruct an incoming message string and add the variables to wave
function processIncomingVariables(incomingVars) {
	var incomingVars = incomingVars.split("|");
	//Go through new variables and place on the wave
	//Start from 1. Pos 0 will be the command
	for(var i = 1; i < incomingVars.length; i++) {
		var newVarKey = incomingVars[i].split("]")[0].split("[")[1];
		var newVarVal = incomingVars[i].split("}")[0].split("{")[1];
		waveIO.append(newVarKey, newVarVal);
		//I dont like this here. It should be that you can continue to append then flush at
		//the end with all changed being propogated to the server. It doesn't work though.
		//So unfortunately extra load for google.
		waveIO.flush();
	}
	waveIO.flush();
}

	
	
	
	
	