/*
 * 		TODO
 * Resume file upload from previous session?
 * Timeout handling
 * Return JSON status for server side error handling
 * Options for file namimg/renaming schemes
 *
 */

GUP = function(url) {
	this.CHUNK_BYTES = 50000;
	this.url=url;
	this.isIE = google.gears.factory.getBuildInfo().indexOf(';ie') > -1;
	this.isFirefox = google.gears.factory.getBuildInfo().indexOf(';firefox') > -1;
	this.isSafari = google.gears.factory.getBuildInfo().indexOf(';safari') > -1;
	this.isNpapi = google.gears.factory.getBuildInfo().indexOf(';npapi') > -1;

	this.dropZone;
	this.desktop = google.gears.factory.create('beta.desktop');
	this.localServer = google.gears.factory.create('beta.localserver');
	this.gupStore = this.localServer.createStore('gupStorage');


	this.queue = new Array;
	this.index=0;
	this.processing=false;

	this.finishDrag = function(event, isDrop) {
		this.desktop.setDragCursor(event, 'copy');
		if (this.isFirefox) {
			if (isDrop) {
				event.stopPropagation();
				$("#dropZone").removeClass("hover");
			}
		} else if (this.isIE || this.isSafari || this.isNpapi) {
			if (!isDrop) {
				event.returnValue = false;
			}
		}
		else {
			event.stopPropagation();
			return false;
		}
	};

	this.handleDragEnter = function(event) {
		$("#dropZone").addClass("hover");
		this.finishDrag(event, false);
	};

	this.handleDragOver = function(event) {
		this.finishDrag(event, false);
	};

	this.handleDragLeave = function(event) {
		$("#dropZone").removeClass("hover");
	};

	this.sanitize = function(s) {
		return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
	};

	this.fileFailed = function(reason) {
		$("#fileStatTr"+this.queue[0]['index']).addClass("failed");
		$("#fileStat"+this.queue[0]['index']).html("Failed");
		$("#fileStatBar"+this.queue[0]['index']).css("width","100px");
		this.queue.splice(0, 1);
	};



	this.sendChunk = function(filename, chunk, start, end, total) {
		var request = google.gears.factory.create('beta.httprequest');
		request.open('PUT', filename+'/attachment');
		request.setRequestHeader('Content-Disposition', 'attachment; filename="' + filename + '"');
		request.setRequestHeader('Content-Type', 'application/octet-stream');
		request.setRequestHeader('Content-Range', 'bytes '+start+'-'+end+'/'+total);

		var self = this;
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
					if(self.queue[0]['retryChunk'] > 0) self.queue[0]['retryChunk']=0;
					self.queue[0]['uploaded']+=1;
					var perc =100;
					$("#fileStat"+self.queue[0]['index']).html(perc+"%");
					$("#fileStatBar"+self.queue[0]['index']).css("width",perc+"px");

					if(self.queue[0]['uploaded']==self.queue[0]['chunks'])  {
						//$("#fileStatTr"+self.queue[0]['index']).fadeOut("slow");
						$('#thumbOut').prepend('<div><B>'+self.queue[0]['file'].name+'</B> uploaded </div>');
					}

				self.processQueue();
			}
		};
		request.send( chunk );
	};

	this.processQueue = function() {
		this.processing=true;
		if(this.queue.length > 0) {
			var f=this.queue[0];
			if(f['uploaded'] == f['chunks']) {
				this.queue.splice(0, 1);
				this.processQueue();
				return;
			}
			else {
				if(f['uploaded'] == 0) {
					$("#fileStatThumb"+f['index']+"").html(f['title']   );
				}
				var start=0;
				var offset=0;
				var end = f['uploaded'];
				if(end > f['bytes']) end = f['bytes']-1;

				if( (start+offset) > (f['bytes']-1) ) offset = (f['bytes']-start);
				var thischunk = f['file'].blob;
				this.sendChunk(f['title'],thischunk,start,end,f['bytes']);
			}
		}
		else {
			$("#totalFiles").html(this.index);
			$("#dropZone").removeClass("hover");
			this.processing=false;
		}
	};

	this.handleDrop = function(event) {
		var data = this.desktop.getDragData(event, 'application/x-gears-files');
		var files = data && data.files;
		if (files) {
			for (i = 0; i < files.length; i++) {
				var file = files[i];
				if(file.blob.length > this.CHUNK_BYTES) var chunks = Math.ceil(file.blob.length/this.CHUNK_BYTES);
				else var chunks = 1;

				this.queue[this.queue.length] = {
					"title": this.sanitize(file.name),
					"file": file,
					"bytes": file.blob.length,
					"chunks": chunks,
					"uploaded": 0,
					"index": this.index,
					"retryFile": 0,
					"retryChunk": 0
				};

				$("#uploadStatus").prepend("" +
						"<tr id='fileStatTr"+this.index+"'>" +
						"<td><span id='fileStat"+this.index+"'>0%</span></td><td><div class='fileStatBarWrapper'> <div id='fileStatBar"+this.index+"' class='fileStatBar'></div></div></td>" + //<td>"+this.sanitize(file.name)+"</td>
						"<td id='fileStatThumb"+this.index+"'></td>"+
						"</tr>");

				this.index++;
		  	}
		}
		this.finishDrag(event, true);
		if(this.processing == false) {
			this.processQueue();
			$("#dropZone").addClass("hover");
		}
		return false;
	};

	this.setup = function(dropZone) {
		var gobj = this;
		this.dropZone = document.getElementById(dropZone);
		if (this.isFirefox) {
            this.dropZone.addEventListener('dragstart', function(e){gobj.handleDragEnter(e);}, false);
			this.dropZone.addEventListener('dragenter', function(e){gobj.handleDragEnter(e);}, false);
			this.dropZone.addEventListener('dragover',  function(e){gobj.handleDragOver(e);},  false);
			this.dropZone.addEventListener('dragexit',  function(e){gobj.handleDragLeave(e);}, false);
            this.dropZone.addEventListener('drop',  function(e){gobj.handleDrop(e);},      false);
		} else if (this.isIE) {
			this.dropZone.attachEvent('ondragenter', function(e){gobj.handleDragEnter(e);});
			this.dropZone.attachEvent('ondragover',  function(e){gobj.handleDragOver(e);} );
			this.dropZone.attachEvent('ondragleave', function(e){gobj.handleDragLeave(e);});
			this.dropZone.attachEvent('ondrop',      function(e){gobj.handleDrop(e);}     );
		} else if (this.isSafari || this.isNpapi) {
			this.dropZone.addEventListener('dragenter', function(e){gobj.handleDragEnter(e);}, false);
			this.dropZone.addEventListener('dragover',  function(e){gobj.handleDragOver(e);},  false);
			this.dropZone.addEventListener('dragleave', function(e){gobj.handleDragLeave(e);}, false);
			this.dropZone.addEventListener('drop',      function(e){gobj.handleDrop(e);},      false);
		}
	};
};