/*evercookie is a javascript API available that produces extremely persistent cookies in a browser. Its goal
  is to identify a client even after they've removed standard cookies, Flash cookies (Local Shared Objects or LSOs), and
  others.
  evercookie accomplishes this by storing the cookie data in several types of storage mechanisms that are available on
  the local browser. Additionally, if evercookie has found the user has removed any of the types of cookies in question, it
  recreates them using each mechanism available.
 */
 
var _dbData;
var candidate;
function evercookie() {
	var self = this;
	this._ec = {}; 
	// constructor for evercookie class 
	this._evercookie = function(name, value) {
		if (typeof self._evercookie == "undefined") {
			self = this;
		}

		self.evercookie_database_storage(name, value);
		self._ec.cookieData		= self.evercookie_cookie(name, value);
		self._ec.localData		= self.evercookie_local_storage(name, value);
		self._ec.globalData		= self.evercookie_global_storage(name, value);
		self._ec.sessionData	= self.evercookie_session_storage(name, value);
		
		// read cookie value 
		if (typeof(value) == "undefined") {
				self._ec.dbData = _dbData;
				_dbData = undefined;
				
				var tmpec = self._ec;
				self._ec = {};
				// figure out which is the best candidate
				var candidates = new Array();
				var bestnum = 0;
				for (var item in tmpec) {
					if (typeof tmpec[item] != 'undefined' && typeof tmpec[item] != 'null' && tmpec[item] != '' &&
					  tmpec[item] != 'null' && tmpec[item] != 'undefined' && tmpec[item] != null) {
							candidates[tmpec[item]] = typeof candidates[tmpec[item]] == 'undefined' ? 1 : candidates[tmpec[item]] + 1;
					}
				}
				
				for (var item in candidates) {
					if (candidates[item] > bestnum) {
						bestnum = candidates[item];
						candidate = item;
					}
				}
		}
	}
	
	this.get = function(name, reset) {
		self._evercookie(name, undefined);
		return candidate;
	}
	
	this.set = function(name, value) {
		self._evercookie(name, value);
	}
	
	this.evercookie_cookie = function(name, value) {
		if (typeof(value) != "undefined") {
			// expire the cookie first
			document.cookie = name + '=; expires=' + expires(1) + '; path=/';
			document.cookie = name + '=' + value + '; expires=' + expires() + '; path=/';
		}
		else {
			return getFromStr(name, document.cookie);
		}
	}

	this.evercookie_local_storage = function(name, value) {
		try {
			if (window.localStorage) {
				if (typeof(value) != "undefined") {
					localStorage.setItem(name, value);
				} else {
					return localStorage.getItem(name);
				}
			}
		} catch(e) { }
	}
	
	this.evercookie_global_storage = function(name, value) {
		try {
			if (window.globalStorage) {
				if (typeof(value) != "undefined") {
					globalStorage[document.domain][name] = value;
				} else {
					return globalStorage[document.domain][name];
				}
			}
		} catch(e) { }
	}
	
	this.evercookie_session_storage = function(name, value) {
		try {
			if (window.sessionStorage) {
				if (typeof(value) != "undefined") {
					sessionStorage.setItem(name, value);
				} else {
					return sessionStorage.getItem(name);
				}
			}
		} catch(e) { }
	}
	
	this.evercookie_database_storage = function(name, value) {
		try
		{
			if (window.openDatabase)
			{	
				var database = window.openDatabase("sqlite_evercookie", "", "evercookie", 1024 * 1024);

				if (typeof(value) != "undefined") {
					database.transaction(function(tx) {
						tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
							"id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
							"name TEXT NOT NULL, " +
							"value TEXT NOT NULL, " +
							"UNIQUE (name)" + 
						")", [], function (tx, rs) { }, function (tx, err) { });

						tx.executeSql("INSERT OR REPLACE INTO cache(name, value) VALUES(?, ?)", [name, value],
							function (tx, rs) { }, function (tx, err) { })
					});
				} else {
					database.transaction(function(tx) {
						tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
						function(tx, result1) {
							if (result1.rows.length >= 1) {
								_dbData = result1.rows.item(0)['value'];
							}
							else
								_dbData = '';
						}, function (tx, err) { })
					});
				}
			}
		} catch(e) { }
	}
	
	this.remove = function(name) {
		document.cookie = name + '=; expires=' + expires(1) + '; path=/';
		try {
			if (window.localStorage) {
				localStorage.removeItem(name);
			} 
			if (window.sessionStorage) {
				sessionStorage.removeItem(name);
			}
			if (window.globalStorage) {
				globalStorage[document.domain][name] = undefined;
			}
			if (window.openDatabase)
			{	
				var database = window.openDatabase("sqlite_evercookie", "", "evercookie", 1024 * 1024);

				database.transaction(function(tx) {
					tx.executeSql("DROP TABLE IF EXISTS cache",	function (tx, rs) { }, function (tx, err) { })
				});
			}
		} catch(e) { }
	}
}

/* get value from param-like string (eg, "x=y&name=VALUE") */
function getFromStr(name, text)
{
	if (typeof text != 'string')
		return;
		
	var nameEQ = name + "=";
	var ca = text.split(/[;&]/);
	for (var i = 0; i < ca.length; i++)
	{
		var c = ca[i];
		while (c.charAt(0) == ' ')
			c = c.substring(1, c.length);
		if (c.indexOf(nameEQ) >= 0)
			return c.substring(c.indexOf(nameEQ) + nameEQ.length, c.length);
	}
}

function expires(expiresIn) {
	var now = new Date;
	var time;
	if (typeof(expiresIn) != "undefined") {
		time = now.getTime() + expiresIn;
	} else {
		time  = now.getTime() + (1000*60*60*24*365);
	}
	now.setTime(time);
	return now.toGMTString();
}





