var EXPORTED_SYMBOLS = ['GrabPicturesService'];

var Application = Components.classes["@mozilla.org/fuel/application;1"]
                  .getService(Components.interfaces.fuelIApplication);

// "bind" is not defined in Firefox3
if (!Function.prototype.bind) {
	Function.prototype.bind = function (context) {
		var __method = this, args = Array.prototype.slice.call(arguments, 1);
		return function() {
			return __method.apply(context, args.concat(Array.prototype.slice.call(arguments, 0)));
		}
	};
}

/***************************************************************************************
 * Basic Structure:
	Group = {
		id: id,
		title: title,
		pictures: []
	}
	Picture = {
		id: id,
		uri: uri,
		weburi: weburi,
		groupId: groupId
	}
 **************************************************************************************/
var GrabPicturesService = {
	picGroupIds: [],
	picGroups: {},
	picObjects: {},
	
	dao: null,
	
	DEFAULT_GROUP_ID: 1,

	initialized: false,
	initService: function() {
		if (this.initialized)
			return;
		this.initialized = true;
		
		var jsm = {};
		Components.utils.import("resource://livemargins/apps/gallery/picdao.js", jsm);
		this.dao = jsm.PictureDAO;
		
		this.dao.init();
		this.loadPicturesData();
	},
	
	getGroups: function() {
		var groups = [];
		for (var i = 0; i < this.picGroupIds.length; i += 1) {
			if (String(this.picGroupIds[i]) in this.picGroups) {
				groups.push(this.picGroups[String(this.picGroupIds[i])]);
			}
		}
		return groups;
	},
	
	getPicObject: function(id) {
		if (String(id) in this.picObjects) {
			return this.picObjects[String(id)];
		}
		
		return null;
	},
	
	getGroupObject: function(id) {
		if (String(id) in this.picGroups) {
			return this.picGroups[String(id)];
		}
		
		return null;
	},
	
	doSaveGroup: function(group, folder) {
		this.dao.saveGroup(group, folder);
	},
	
	doSavePictures: function(folder) {
		var groups = this.getGroups();
		this.dao.savePictures(groups, folder);
	},
	
	loadPicturesData: function(){
		if (this.dao) {
			// load group
			var groups = this.dao.getGroups();
			for (var i = 0; i < groups.length; i += 1) {
				var id = groups[i].id;
				this.picGroupIds.push(id);
				this.picGroups[String(id)] = {
					id: groups[i].id,
					title: groups[i].title,
					pictures: []
				};
				logObject(this.picGroups[String(id)]);
			}
			
			// load pictures
			var pictures = this.dao.getPictures();
			for (var i = 0; i < pictures.length; i += 1) {
				var pid = pictures[i].id;
				var gid = pictures[i].groupId;
				if (String(gid) in this.picGroups) {
					this.picGroups[String(gid)].pictures.push(pictures[i]);
					this.picObjects[String(pid)] = pictures[i];
					logObject(pictures[i]);
				} else {
					log("Something is wrong, got groupId=" + groupId + " but not in the Group map!");
				}
			}
		}
	},
	
	addPicture: function(uri, webUri, groupId) {
		log("add picture " + uri + ";" + webUri + ";" + groupId);
		
		if (!(String(groupId) in this.picGroups)) {
			log("Something is wrong, got groupId=" + groupId + " but not in the Group map!");
			return;
		}
		
		var pid = this.dao.addPicture(uri, webUri, groupId);
		this.dao.cachePicture(uri, false);

		var picObject = {
			id: pid,
			uri: uri,
			weburi: webUri,
			groupId: groupId
		};
		logObject(picObject);
		this.picGroups[String(groupId)].pictures.push(picObject);
		this.picObjects[String(pid)] = picObject;
		
		return pid;
	},
	
	removePicture: function(id, clearCache) {
		var picObject = this.getPicObject(id);
		if (picObject) {
			log("remove picture #" + id);
			if (String(picObject.groupId) in this.picGroups) {
				var group = this.picGroups[String(picObject.groupId)];
				for (var i = 0; i < group.pictures.length; i += 1) {
					if (group.pictures[i].id === picObject.id) {
						group.pictures.splice(i, 1);
						break;
					}
				}
			}
			delete this.picObjects[String(id)];
			
			this.dao.removePicture(id, picObject.uri, clearCache);
		}
	},
	
	getLocalCache:function(uri) {
		return this.dao.getLocalCache(uri);
	},
	
	getThumbnail: function(uri) {
		return this.dao.getThumbnail(uri);
	},
	
	createThumbnail: function(uri, data) {
		this.dao.createThumbnail(uri, data);
	},
	
	addGroup: function(title) {
		log("addgroup " + title);
		
		var gid = this.dao.addGroup(title);
		
		var groupObj = {
			id: gid,
			title: title,
			pictures: []
		};
		logObject(groupObj);
		this.picGroupIds.push(gid);
		this.picGroups[String(gid)] = groupObj;
		
		return groupObj;
	},
	
	setGroupTitle: function(id, name) {
		log('setting title ' + name + " for group #" + id);
		if (!(String(id) in this.picGroups)) {
			log("Something is wrong, the group #" + id + " is not in the map!");
			return;
		}
		
		var groupObj = this.picGroups[String(id)];
		groupObj.title = name;
		
		this.dao.updateGroup(id, name);
	},
	
	removeGroup: function(id) {
		log("remove group #" + id);
		
		if (!(String(id) in this.picGroups)) {
			log("Something is wrong, the group #" + id + " is not in the map!");
			return;
		}
		
		// front end will make sure that this is an empty group;
		
		var groupObj = this.picGroups[String(id)];
		delete this.picGroups[String(id)];
		for (var i = 0; i < this.picGroupIds.length; i += 1) {
			if (this.picGroupIds[i] == id) {
				this.picGroupIds.splice(i, 1);
				break;
			}
		}
		
		this.dao.removeGroup(id);
	},
	
	savePageAsPicture: function() {
		var main = this.mainWindow;

		var webUri = this.getCurrentTabLink();
		var localuri = this.dao.captureWindow(main, webUri);
		Application.console.log(localuri);
		
		if (localuri) {
			var self = this;
			this.mainWindow.setTimeout(function() {
				var picId = self.addPicture(localuri, webUri, self.DEFAULT_GROUP_ID);
			}, 1000);
		}
	},
	
	getFileURI: function(localuri) {
		var localfile = Components.classes["@mozilla.org/file/local;1"].
					createInstance(Components.interfaces.nsILocalFile);
		localfile.initWithPath(localuri);
		var ioService = Components.classes["@mozilla.org/network/io-service;1"].
					getService(Components.interfaces.nsIIOService);
		return ioService.newFileURI(localfile).spec;
	},
	
	dispose: function(){
		if (this.dao) {
			this.dao.dispose();
		}		
	},
		
	get mainWindow() {
		var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
		                   .getService(Components.interfaces.nsIWindowMediator);
		var mainWindow = wm.getMostRecentWindow("navigator:browser");
		return (mainWindow);
	},

	openLink: function(link) {
		this.mainWindow.getBrowser().loadOneTab(link, null, null, null, false, false);
	},
	
	getCurrentTabLink: function() {
		var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
		                   .getService(Components.interfaces.nsIWindowMediator);
		var recentWindow = wm.getMostRecentWindow("navigator:browser");
		return recentWindow ? recentWindow.content.document.location.toString() : null;
	},
	
	onDragGesture: function(event) {
		var deltaX = event.endX - event.startX;
		var deltaY = event.endY - event.startY;
		
		if (deltaX * deltaX + deltaY * deltaY <= 64) {
			// not drag long enough I think
			return false;
		}
		
		if (event.type === 'image') {
			var uri = event.data;
			var webUri = this.getCurrentTabLink();
			var picId = this.addPicture(uri, webUri, this.DEFAULT_GROUP_ID);
//			this.mainWindow.marginBoxUI.openPreviewPanel(this, {
//				selectId: picId
//			});
			return true;
		}
		return false;
	},
	
};

GrabPicturesService.initService();

function logObject(obj) {
	var x = [];
	for (var key in obj) {
		if (typeof obj[key] === 'function') {
			x.push(key + ": function");
		} else {
			x.push([key, obj[key]].join(' = '));			
		}
	}
	log(x.join('\r\n'));
}

function log(msg) {
	var debug = false;
	if (debug) {
		Application.console.log("[MB-GrabPic] " + msg);
	}
}
