var Components = null;
var debug = false;
function log(msg) {
	if (!debug) {
		return;
	}
	
	if (Components) {
		Components.utils.reportError(msg);
	}
}

onmessage = function(event) {
	log('event.data: ' + event.data);
	switch (event.data.symbol) {
		case 'components':
			Components = event.data.components;
			log('Received Components Object.');
			PicSaveWorker.init();
			break;
		case 'savepictures':
			PicSaveWorker.savePictures(event.data.groups, decodeURI(event.data.folder));
			break;
		case 'savegroup':
			PicSaveWorker.saveGroup(event.data.group, decodeURI(event.data.folder));
			break;
		case 'cachepic':
			PicSaveWorker.cachePicture(event.data.pictureUri);
			break;
	}
}

var Application = null;
var dirService = null;

var DEFAULT_GROUP_ID = 1;

var PicSaveWorker = {
	firstRun: false,
	OS: null,
	
	init: function() {
		Application = Components.classes["@mozilla.org/fuel/application;1"]
				.getService(Components.interfaces.fuelIApplication);

		dirService = Components.classes["@mozilla.org/file/directory_service;1"]
						.getService(Components.interfaces.nsIProperties);
		// Returns "WINNT" on Windows Vista, XP, 2000, and NT systems;  
		// "Linux" on GNU/Linux; and "Darwin" on Mac OS X.  
		this.OS = Components.classes["@mozilla.org/xre/app-info;1"]
						.getService(Components.interfaces.nsIXULRuntime).OS;  
	},
	
	get mainThread() {
		var main = Components.classes["@mozilla.org/thread-manager;1"].getService().mainThread;
		return (main);
	},
	
	cachePicture: function(pictureUri) {
		if (!this.localExists(pictureUri)) {
			log("Miss Cache: " + pictureUri);
			log("CacheTask - " + pictureUri);
			var cacheFolder = this.getCacheFolder();
			var path = this.internalSavePicture(pictureUri, cacheFolder, true);
			log('CacheDone - ' + pictureUri + " - " + path);
		} else {
			log("Hit Cache: " + uri);
		}
	},
	
	localExists: function(uri) {
		var file = this.getCacheFolder();
		file.append(this.md5(uri));
		return file.exists() && !file.isDirectory();
	},

	removeCache: function(uri) {
		if (this.localExists(uri)) {
			var file = this.getCacheFolder();
			file.append(this.md5(uri));
			file.remove(true);
			
			log('Cache Removed: ' + uri);
		}
	},
	
	get filePath () {
		if (this.OS == "Darwin" || this.OS == "Linux") {
			return "LiveMargins_Mac_Linux";
		} else {
			return "LiveMargins";
		}
	},
	
	getCacheFolder: function() {
		var cacheFolder = dirService.get('UChrm', Components.interfaces.nsIFile);
		cacheFolder.append(this.filePath);
		cacheFolder.append("files");
		
		if (!cacheFolder.exists() || !cacheFolder.isDirectory()) {
			cacheFolder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0766);
		}
		return cacheFolder;
	},
	
	// save picture
	saveGroup: function(group, folder){
		log("SaveGroupTask - " + group.title);
		
		var localFolder = Components.classes["@mozilla.org/file/local;1"]
                .createInstance(Components.interfaces.nsILocalFile);
		localFolder.initWithPath(folder);
		
		this.internalSaveGroup(group, localFolder);
		localFolder.launch();
	},
	
	savePictures: function(groups, folder) {
		log("SavePicturesTask: " + folder);
		var localFolder = Components.classes["@mozilla.org/file/local;1"]
							.createInstance(Components.interfaces.nsILocalFile);
		localFolder.initWithPath(folder);
		for (var i = 0; i < groups.length; i += 1) {
			this.internalSaveGroup(groups[i], localFolder);
		}
		localFolder.launch();
	},
	
	internalSaveGroup: function(group, folder) {
		var groupName = "";
		if (group.id == DEFAULT_GROUP_ID) {
			groupName = "Default";
		} else {
			groupName = group.title;
		}

		try {
			var groupFolder = Components.classes["@mozilla.org/file/local;1"].
						createInstance(Components.interfaces.nsILocalFile);
			groupFolder.initWithFile(folder);
			groupFolder.append(groupName);
			if (!groupFolder.exists() || !groupFolder.isDirectory()) {
				groupFolder.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0766);
			}

			
			for (var i = 0; i < group.pictures.length; i += 1) {
				var picture = group.pictures[i];
				if (this.localExists(picture.uri)) {
					this.internalCopyCache(picture.uri, groupFolder, false);
				} else {
					this.internalSavePicture(picture.uri, groupFolder, false);					
				}
			}
		} catch (e) {
			log(e);
		}
	},
	
	// copy the cache picture to folder
	internalCopyCache: function(uri, folder) {
		log("Copy cache file to folder: " + uri);
		var localfile = this.getCacheFolder();
		localfile.append(this.md5(uri));
		
		var filename = uri;
		filename = filename.substring(filename.lastIndexOf('/') + 1);
		if (filename.lastIndexOf('.') < filename.length - 5){
			filename += ".jpg";
		}			
		filename = new Date().getTime() + "_" + encodeURIComponent(filename);
		if (filename) {
			localfile.copyTo(folder, filename);
		}
	},
	
	// Returns cache file's local path name like "/Users/xxx/Application...."
	internalSavePicture: function(uri, folder, md5name) {
		// nsIIOService is not threadsafe, cannot use in non-main thread
		// so post message back to main thread to save cache
		postMessage({
			symbol: "savepicture",
			uri: uri,
			folder: folder.path,
			md5name: md5name
		});
	},
	
	md5 :function(s) {
		var str = s;
		var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);

		// we use UTF-8 here, you can choose other encodings.
		converter.charset = "UTF-8";
		// result is an out parameter,
		// result.value will contain the array length
		var result = {};
		// data is an array of bytes
		var data = converter.convertToByteArray(str, result);
		var ch = Components.classes["@mozilla.org/security/hash;1"].createInstance(Components.interfaces.nsICryptoHash);
		ch.init(ch.MD5);
		ch.update(data, data.length);
		var hash = ch.finish(false);

		// return the two-digit hexadecimal code for a byte
		var toHexString = function(charCode) {
			return ("0" + charCode.toString(16)).slice(-2);
		}
		// convert the binary hash data to a hex string.
		var s = [];//[for (var i=0;i<hash.length;i++) toHexString(hash.charCodeAt(i))].join("");
		for(var i=0;i<hash.length;i++) {
			var result = toHexString(hash.charCodeAt(i));
			s.push(result);
		}
		s = s.join("");
		return s;
	},
	
};

