﻿/// <reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5-vsdoc.js" />
/// <reference path="debugversions/ba-debug.js" />
/// <reference path="debugversions/squirrel.1.0.js" />

//TODO: handle running out of space
//TODO: migrate from Squirrel to web sql where we can a) store more content, b) have more control

_b.ClientCache = {
	// Instantiate a new Squirrel cache
	_cache: new Squirrel("bondi", 3600 * 24 * 365),

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	clearSubCache: function (subCache) {
		///<summary>Clears a specific subCache, by name.</summary>
		///<param name="subCache">Name of sub cache, required</param>
		///<returns type="Boolean">true/false indicating success</return>
		return !!subCache && this._cache.clear(subCache);
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	cacheObject: function (subCache, key, jsonObject) {
		/// <summary>Caches a json object</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="key" type="String">The cache key</param>
		/// <param name="jsonState" type="Object">The object to cache in json notation</param>
		///<returns type="Boolean">true/false indicating success</return>
		var stringData = JSON.stringify(jsonObject), result;
		try {
			result = this._cache.write(subCache, key, stringData); 
		}
		catch (exc) {
			//handle apparent iPad 3.2 bug in which the cached item must be removed prior to insert
			if (exc.name === "QUOTA_EXCEEDED_ERR") {
				try {
					this._cache.remove(subCache, key);
					result = this._cache.write(subCache, key, stringData);
					if (!result) {
						debug.log("Secondary cache attempt failed");
					}
				}
				catch (exc2) {
					debug.error("Secondary cache attempt error: " + exc2.name);
					result = false; 
				}
			} else {
				result = false;
			}
		}
		return !!result;
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	getCachedObject: function (subCache, key) {
		/// <summary>Caches a json object</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="key" type="String">The cache key</param>
		///<returns type="Object">The cached object in json notation</return>
		var data;
		try {
			data = this._cache.read(subCache, key);
			data = JSON.parse(data);
		}
		catch (e) { }
		return data;
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	getThenCache: function (subCache, url, type, success, error) {
		///	<summary>
		///		Loads content from the server using an HTTP GET request, then caches the content in localStorage.
		///	</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="url" type="String">The URL of the content to load - also used as cache key.</param>
		///	<param name="type" type="String">Type of data to be returned to callback function.  Valid values are html, json, text</param>
		///	<param name="success" type="Function">Success callback: function(data, status, xhr).</param>
		///	<param name="error" type="Function">Error callback: function(xhr, status, error).</param>

		var doCache = _b.Core.useCache
		var stringData = "";

		//first clear out what was there
		this._cache.remove(subCache, url);

		//then execute a jQuery Ajax Get
		jQuery.ajax({
			type: "GET",
			url: url,
			success: function (data, status, xhr) {
				//convert data to a string, if needed 
				try {
					switch (type) {
						case "json":
							stringData = JSON.stringify(data);
							break;
						case "xml":
							stringData = (new XMLSerializer()).serializeToString(data);
							break;
						default:
							stringData = data.toString();
					}
				}
				catch (e) { doCache = false; };

				//cache the stringified data in the subCache, set status if not successful, then callback with the original data
				status = (doCache && _b.ClientCache._cache.write(subCache, url, stringData)) ? status : "NOTCACHED";
				success(data, status, xhr);
			},
			error: error,
			dataType: type
		});
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	cachedGet: function (subCache, url, type, forceRefresh, success, error) {
		///	<summary>
		///		Loads content from the cache or the server using an HTTP GET request.
		///	</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="url" type="String">The URL of the content to load - also used as cache key.</param>
		///	<param name="type" type="String">Type of data to be returned to callback function.  Valid values are html, json, text.</param>
		///	<param name="forceRefresh" type="Boolean">Whether to force a refresh from the server.</param>
		///	<param name="success" type="Function">Success callback: function(data, status, xhr).</param>
		///	<param name="error" type="Function">Error callback: function(xhr, status, error).</param>
		var cachedData = this._cache.read(subCache, url);
		if (!forceRefresh && cachedData && _b.Core.useCache) {
			success(cachedData, "FROMCACHE");
		} else {
			this.getThenCache(subCache, url, type, success, error);
		}
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	cachedGetJSON: function (subCache, url, forceRefresh, success, error) {
		///	<summary>
		///		Loads parsed JSON from the cache or from the server using an HTTP GET request.
		///	</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="url" type="String">The URL of the content to load - also used as cache key.</param>
		///	<param name="forceRefresh" type="Boolean">Whether to force a refresh from the server.</param>
		///	<param name="success" type="Function">Success callback: function(jsonData, status, xhr).</param>
		///	<param name="error" type="Function">Error callback: function(xhr, status, error).</param>
		this.cachedGet(subCache, url, "json", forceRefresh,
			function (data, status, xhr) {
				if (status === "FROMCACHE" && JSON) {
					try { data = JSON.parse(data); }
					catch (e) { }
				}
				success(data, status, xhr);
			},
			error);
	},

	/*______________________________________________________________________________________________________________________________________________________________________________________*/
	cachedGetHtml: function (subCache, url, forceRefresh, success, error) {
		///	<summary>
		///		Loads html content from the cache or the server using an HTTP GET request.
		///	</summary>
		///	<param name="subCache" type="String">Name of sub cache to use</param>
		///	<param name="url" type="String">The URL of the content to load - also used as cache key.</param>
		///	<param name="forceRefresh" type="Boolean">Whether to force a refresh from the server.</param>
		///	<param name="success" type="Function">Success callback: function(htmlData, status, xhr).</param>
		///	<param name="error" type="Function">Error callback: function(xhr, status, error).</param>
		this.cachedGet(subCache, url, "html", forceRefresh, success, error);
	}

};

