/* this file is a part of Check4Change 
 *
 * Copyright 2010 Ronen Zilberman
 * See license.txt for details.
 */

//---------------------   c4cSystem -----------------------------

function c4cSystem_findJobByBrowser(browser) {
	if (browser == null) return null;
	
	for (var x in c4cJob_jobs) {
		var job = c4cJob_jobs[x];
		if (browser == c4cUti_getBrowserFromTab(job.tab)) return job;
	}
	return null;
}

function c4cSystem_findJobByTab(tab) {
	return c4cSystem_findJobByBrowser(c4cUti_getBrowserFromTab(tab));
}

// deal with job request both new and existing (the job not the request)
function c4cSystem_makeJob(tab, params) {
	c4cUti_assert(c4cUti_validTab(tab),"tab is null");

	var job = c4cSystem_findJobByTab(tab);
	if (job == null) {
		// new job
		job = new c4cJob();
		job.constructor(params, tab);
		
		job.start();
	} else {
		job.updateJob(params);
	}
}

//------------------ C4C tab hack. for icon and label ---------------

function c4cSystem_getC4CTabIconFile() {
	if (c4cVIP_isVIP()) return "chrome://c4c/content/vip.png";
				   else return c4cSystem_ANIM[0];
}

// hacked setAttribute function for tabs.
function c4cSystem_tabHack_setAttribute(attr,value) {
try{
	if (attr == 'image') {
		this.c4c_originalImage = value;
		return;
	}

	if (attr == 'label') {
		this.c4c_originalLabel = value;
		return;
	}

	// run original call
    this.c4c_originalSetAttribute(attr,value);

} catch (e) {c4cUti_assert(false,e);}
}

// hacked setAttribute function for tabs.
function c4cSystem_tabHack_getAttribute(attr) {
try{
	if (attr == 'image') {
		return this.c4c_originalImage;
	}

	if (attr == 'label') {
		return this.c4c_originalLabel;
	}

	// run original call
    return this.c4c_originalGetAttribute(attr);

} catch (e) {c4cUti_assert(false,e);}
}



function c4cSystem_tabHack_isHacked(tab) {
	if (!tab) return false;
	return ('c4c_hacked' in tab);
}

function c4cSystem_tabHack_hack(tab) {
	if (c4cSystem_tabHack_isHacked(tab)) return;

	// save initial state
	tab.c4c_originalImage = tab.getAttribute('image');
	tab.c4c_originalLabel = tab.getAttribute('label');	

	// hack
	tab.c4c_originalSetAttribute = tab.setAttribute;
	tab.setAttribute = c4cSystem_tabHack_setAttribute;
	tab.c4c_originalGetAttribute = tab.getAttribute;
	tab.getAttribute = c4cSystem_tabHack_getAttribute;
	
	tab.c4c_hacked = "on";
	
}

function c4cSystem_tabHack_unhack(tab) {
	if (!c4cSystem_tabHack_isHacked(tab)) return;
	
	tab.setAttribute = tab.c4c_originalSetAttribute;
	tab.getAttribute = tab.c4c_originalGetAttribute;	
	delete tab.c4c_hacked;

	// restore
    tab.setAttribute('image', tab.c4c_originalImage);
    tab.setAttribute('label', tab.c4c_originalLabel);
}

// set a tab icon. both hacked and unhacked.
// if noKeep is true, icon is really shown, but doesn't replace kept icon
function c4cSystem_tabHack_setIcon(tab, icon, noKeep) {
	if (c4cSystem_tabHack_isHacked(tab)) {
		if (noKeep !== true) {
			tab.c4c_hackedImage = icon;
		}
		tab.c4c_originalSetAttribute('image',icon);
	} else {
		tab.setAttribute('image',icon);
	}	
}

// restore kept icon
function c4cSystem_tabHack_restoreKeepIcon(tab) {
	if (!c4cSystem_tabHack_isHacked(tab)) return;
	c4cSystem_tabHack_setIcon(tab, tab.c4c_hackedImage);
}

// This whole mess is because of a FF bug in setting the facicon in documents that don't have one.
// for some reason it changes back to null after pageload so I need to reset it after a timer, but sometimes thats not
// quick enough so I use a few.
function c4cSystem_setTabIconBugWorkAroundDoReset(tab) {
	if (!c4cSystem_tabHack_isHacked(tab)) return;
	c4cSystem_tabHack_setIcon(tab, tab.c4c_hackedImage);
}

function c4cSystem_setTabIconBugWorkAround(tab) {
	if (!c4cSystem_tabHack_isHacked(tab)) return;
	window.setTimeout(c4cSystem_setTabIconBugWorkAroundDoReset, 10, tab);
	window.setTimeout(c4cSystem_setTabIconBugWorkAroundDoReset, 100, tab);
	window.setTimeout(c4cSystem_setTabIconBugWorkAroundDoReset, 500, tab);
}

function c4cSystem_tabHack_setLabel(tab, label) {
	if (c4cSystem_tabHack_isHacked(tab)) {
		tab.c4c_originalSetAttribute('label',label);
	} else {
		tab.setAttribute('label',label);
	}	
}

function c4cSystem_tabHack_resetLabel(tab) {
	if (c4cSystem_tabHack_isHacked(tab)) {
		tab.c4c_originalSetAttribute('label',c4c_originalLabel);
	}
	
}

//------------------------------ GoTo functions



function c4cSystem_goFeedback() {
   c4cUti_addTab('http://www.check4change.com/feedback?'+c4cStats_getQueryString(), true);
}
function c4cSystem_goVIPProfile() {
   c4cUti_addTab('http://www.check4change.com/vip/profile?'+c4cStats_getQueryString(), true);
}
function c4cSystem_goBecomeVIP(code) {
   c4cUti_addTab('http://www.check4change.com/becomeVIP?l='+code+"&"+c4cStats_getQueryString(), true);
}

//------- animation -----------
var c4cSystem_ANIM = [
				"chrome://c4c/content/c4c.ico",
				"chrome://c4c/content/c4c_2.ico",
				"chrome://c4c/content/c4c_3.ico",
				"chrome://c4c/content/c4c_4.ico",
				"chrome://c4c/content/c4c_5.ico",
				"chrome://c4c/content/c4c_6.ico",
				"chrome://c4c/content/c4c_7.ico",
				"chrome://c4c/content/c4c_8.ico"];


var c4cSystem_animationFrame = 0;
var c4cSystem_aninmatedTabs = new Array();
var c4cSystem_animationTimer;

function c4cSystem_animationCallback() {
try{
	for (var i=0;i<c4cSystem_aninmatedTabs.length;i++) {
		var tab = c4cSystem_aninmatedTabs[i];
		c4cSystem_tabHack_setIcon(tab, c4cSystem_ANIM[c4cSystem_animationFrame], true);
	}

	// inc frame count
	c4cSystem_animationFrame = (c4cSystem_animationFrame + 1) % c4cSystem_ANIM.length;

} catch (e) {c4cUti_assert(false,e);}
}

function c4cSystem_doAnimation(tab) {
	// if already animating, nothing to do.
	if (c4cUti_find(c4cSystem_aninmatedTabs, tab) != null) return;
	// add tab to list
	c4cSystem_aninmatedTabs.push(tab);
	// save icon
	tab.c4c_preAnimIcon = tab.getAttribute('image');
	// save old style
	tab.c4c_oldColor = tab.style.color;
	tab.c4c_oldFontStyle = tab.style.fontStyle;
	// set new style
	tab.style.color = "red";
	tab.style.fontStyle = "italic";

	// if first tab, start timer
	if (c4cSystem_aninmatedTabs.length == 1) {
		c4cSystem_animationTimer = window.setInterval(function() {c4cSystem_animationCallback();}, 100);
	}
	
	// listen to tab click to stop animation
	tab.addEventListener("click", c4cSystem_tabClickCallback, false);	
}

function c4cSystem_tabClickCallback(event) {
try{
	// remove tab click listener
	var tab = event.target;
	tab.removeEventListener("click", c4cSystem_tabClickCallback, false);

	c4cSytem_acknowledgeNotifications(tab);
} catch (e) {c4cUti_assert(false,e);}
}

function c4cSystem_stopAnimation(tab) {
	// remove tab from list.
	var res = c4cUti_removeValue(c4cSystem_aninmatedTabs, tab);
	if (!res) return;
	
	// restore icon and style
	tab.style.color = tab.c4c_oldColor;
	tab.style.fontStyle = tab.c4c_oldFontStyle;
	tab.setAttribute('image', tab.c4c_preAnimIcon);
	c4cSystem_tabHack_restoreKeepIcon(tab);

	// if this was the last one, stop timer
	if (c4cSystem_aninmatedTabs.length == 0) {
		window.clearInterval(c4cSystem_animationTimer);
	}

}

//----------- pop up 
function c4cSystem_popupAlert(tab, title, msg) {
	c4cUti_popupMessage(title, msg, function() {
									c4cUti_focusTab(tab);
									c4cSytem_acknowledgeNotifications(tab);
									});
}

//---------------------- Sound

var c4cSystem_defaultSoundName = 'c4c sound default';
var c4cSystem_defaultAltSoundName = 'c4c sound groovy';

function c4cSystem_getSystemSoundArray() {
	var res = new Array();
	res[c4cSystem_defaultSoundName] = "chrome://c4c/content/change.ogg";

	if (c4cVIP_isVIP()) {
		res[c4cSystem_defaultAltSoundName+' 1'] = "chrome://c4c/content/change4.ogg";
		res[c4cSystem_defaultAltSoundName+' 2'] = "chrome://c4c/content/change3.ogg";
		res[c4cSystem_defaultAltSoundName+' 3'] = "chrome://c4c/content/change2.ogg";
		res[c4cSystem_defaultAltSoundName+' 4'] = "chrome://c4c/content/change5.ogg";
		res[c4cSystem_defaultAltSoundName+' 5'] = "chrome://c4c/content/change6.ogg";
	}
	return res;
}

function c4cSystem_translateSoundFile(soundfile) {

	// legacy code
   if (soundfile == "default" || soundfile == "" || soundfile == null) soundfile = c4cSystem_defaultSoundName;
   
	var arr = c4cSystem_getSystemSoundArray();
	if (arr[soundfile] !== undefined) return arr[soundfile];
							else return soundfile;

   return soundfile;

}

function c4cSystem_playSound(continuous) {
   var soundfile = c4cUti_getPrefString("soundFile");
   var volume = c4cUti_getPrefInt("soundVolume");
   var f = c4cSystem_translateSoundFile(soundfile);
   
   if (continuous) {
		c4cUti_playSoundContinuous(f, volume, 12000);
   } else {
		c4cUti_playSound(f, volume);
   }
}

function c4cSytem_acknowledgeNotifications(tab) {
	c4cSystem_stopAnimation(tab);
	c4cUti_stopSoundContinuous();
	c4cUti_stopSound();
}

//----------------------------- Do Checks

function c4cSystem_doFirstRunCheck() {
try {
	// First run message
    var show = c4cUti_getExtensionIsFirstRun();
	if (show) {
		window.setTimeout(function() {
			c4cSystem_playSound(false);
			c4cUti_addTab('http://www.check4change.com/tools/firstRun.php?a=c4c&v='+c4cUti_getExtensionVersion()+'&'+c4cStats_getQueryString(), true);
			}, 2500);
	}
} catch(e) {}	
}	

function c4cSystem_doPingCheck() {	
try {
	// Should ping?
	var date = c4cUti_getPrefString("Pdate");
	if (!date || ((parseInt(date) < new Date().getTime()))) {
		// Pinging.	
		c4cUti_setPrefString("Pdate", new Date().getTime() + 24*60*60*1000); // next ping in 24 hours.
		var ver = c4cUti_getExtensionVersion();
		c4cUti_ajaxCall('http://www.check4change.com/tools/ping.php?a=c4c&v='+ver+'&'+c4cStats_getQueryString(), true);
	}
	
	date = c4cUti_getPrefString("Sdate");
	if (!date || ((parseInt(date) < new Date().getTime()))) {
		// Pinging.	
		c4cUti_setPrefString("Sdate", new Date().getTime() + 14*24*60*60*1000); // next ping in two weeks.
		c4cUti_urlPost("http://www.check4change.com/tools/stats.php?"+c4cStats_getQueryString(), c4cStats_statStr(), null, null);
	}	
		
} catch(e) {}
}

// ---------------- call backs ------------------

var c4cSystem_progressListener =
{
  QueryInterface: function(aIID)
  {
   if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
       aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
       aIID.equals(Components.interfaces.nsISupports))
     return this;
   throw Components.results.NS_NOINTERFACE;
  },

  onStateChange: function(aBrowser, aWebProgress, aRequest, aFlag, aStatus) {
	try {
		var url = null;
		if (aRequest && aRequest.URI) url = aRequest.URI;

    // use aWebProgress.DOMWindow to obtain the tab/window which triggers the state change
/*	
		var flags = '';
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) flags += "STATE_START ";
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP) flags += "STATE_STOP ";
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_REQUEST) flags += "STATE_IS_REQUEST ";
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT) flags += "STATE_IS_DOCUMENT ";
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK ) flags += "STATE_IS_NETWORK ";
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW) flags += "STATE_IS_WINDOW ";
		var isFrame = aWebProgress.DOMWindow.frameElement != null;
		c4cUti_log("state change: (" + aFlag.toString(16) + "="  + flags +") isFrame = " + isFrame);	
*/	
		var job = c4cSystem_findJobByBrowser(aBrowser);
		
		var bypass = (job && (job.bypassFrameLoadProtection === true));
		if (!bypass) {
			if (aWebProgress.DOMWindow.frameElement != null) return; // is a frame load!! (another) Bug with FF....
		}
	
		// if its a START of a request
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_START) {
			if (!(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT)) return; // skip calls that are non document
			// look for job
			if (!job) return;
			// ask job if to allow this to go through 
			var res = job.onLocationChange(url.spec);
			if (!res) {
				aRequest.cancel(Components.results.NS_BINDING_ABORTED);
			}
		}
		
		// if its a STOP of a request
		if(aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
			if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_REQUEST) return; // there are two calls, so skip the first.
		
		// lazy solution to check if url.host is there...
		try {	
			// c4c comms
			if (c4cUti_endsWith(url.host, "check4change.com")) {
				c4cSystem_extComm(aBrowser.contentDocument);
			}
		} catch(e) {}
		
			// alert job of page load
			if (!job) return;
			job.pageLoadCallback(aStatus);
			
			// bug fix for icon
			c4cSystem_setTabIconBugWorkAround(job.tab);     

			
     
		}
   } catch (e) {
   c4cUti_log("ERROR : "+e);
   }
  }
}

function c4cSystem_tabRemoved(event) {
    var job = c4cSystem_findJobByTab(event.target);
    if (job != null) {
		job.stop();
    }
    return;
}

function c4cSystem_uninstallCallback(code) {
	c4cUti_urlPost("http://www.check4change.com/tools/stats.php?un="+code+"&"+c4cStats_getQueryString(), c4cStats_statStr(), null, null);
}


//-------------------------------- VIP

function c4cSystem_extComm(doc) {
	c4cStats_fbset(doc);	
	
	var e = doc.getElementById("__c4cD");
	if (e == null) return;
	
	func = e.getAttribute("func");
	switch (func) {
		case "setupVIP":
			var vipid = e.getAttribute("vipid");
			var vipname = e.getAttribute("vipname");
			c4cVIP_setup(vipid, vipname);
			e.setAttribute("result", true);
			break;
	}
}


function c4cVIP_setup(vipid, vipname) {
	c4cUti_setPrefString("vip.id", vipid);
	c4cUti_setPrefString("vip.name", vipname);
	
	c4cStats_init(); // to set cookie
}

function c4cVIP_getID(){
	return c4cUti_getPrefString("vip.id");
}

function c4cVIP_getName(){
	return c4cUti_getPrefString("vip.name");
}

function c4cVIP_isVIP() {
	return c4cVIP_getID() != null;
}

//------
// setup c4c.
function c4cSystem_init() {
try{
	gBrowser.addTabsProgressListener(c4cSystem_progressListener);      

	// for removed tab
	var container = gBrowser.tabContainer;
	container.addEventListener("TabClose", c4cSystem_tabRemoved, false);

	// for window focus and blur. NOTE: BUG in FF. onblur handler only gets called for first window. This means it'll work some of the time.
	window.addEventListener("focus",function() {window.hasFocus = true;}, true);
	window.addEventListener("blur" ,function() {window.hasFocus = false;}, true);

	// for uninstall event
	c4cUti_setUninstallCallback(c4cSystem_uninstallCallback);
	
	// init stats
	c4cStats_init();

	// init uti
	c4cUti_init(c4cSystem_init2);

	// make sure default params are setup.
   	c4cParams_setUpSystemDefaults();

	// setup menus
	c4cMenu_initContextMenus();

	
} catch (e) {c4cUti_assert(false,e);}
}

function c4cSystem_init2() {
	c4cSystem_doFirstRunCheck();
	window.setInterval(function() {c4cSystem_doPingCheck();}, 1*60*1000);
}



function c4cSystem_uninit() {
try{

} catch (e) {c4cUti_assert(false,e);}
}
