/**
 * Copyright 2015 Washington University
 * File uploader
 * Author:  Mike Hodge (hodgem@wustl.edu)
 */

var abu = abu || {};

abu.initializeUploader = function(initarr){
	abu._fileUploader = new abu.FileUploader(initarr);
};

abu.FileUploader = function(o){

	this._options = o;
	// NOTE:  Multiple concurrent cache uploads works fine, but multiple concurrent uploads to a resource often causes failures and can corrupt the catalog.
	// Leave this set to 1 if the uploader supports uploading directly to resources.
	this.MAX_CONCURRENT_UPLOADS = 1;
	this.ALLOW_DRAG_AND_DROP = true;
	this.DRAG_AND_DROP_ON = true;
	this.uploadsInProgress = 0;
	this.uploadsStarted = 0;
	this.overwriteConfirmIssued = false;
	this.doOverwrite = false;
	$(this._options.element).html(""); 

	this.buildUploaderDiv = function() {
		$(this._options.element).append(
			'<div class="abu-uploader">' +
				'<div id="abu-files-processing" class="abu-files-processing">        Processing...... </div>' +
				'<a id="file-uploader-instructions-sel" class="abu-uploader-instructions-sel" onclick="abu._fileUploader.uploaderHelp()">?</a>' +
				'<div class="abu-upload-drop-area" style="display: none;"><span>Drop files here to upload</span></div>' +
				'<div class="abu-xnat-interactivity-area">' +
				'</div>' +
			'<div id="abu-upload-button" class="abu-upload-button" style="position: relative; overflow: hidden; direction: ltr;">' + 
				'Upload files<input multiple="multiple" type="file" id="file-upload-input" class="abu-button-input">' + 
			'</div>' +
			'<div id="abu-done-button" class="abu-done-button" style="position: relative; overflow: hidden; direction: ltr;">' + 
				'<span id="abu-done-button-text" class="abu-done-button-cancel">Cancel</span><input type="image" name="done" class="abu-button-input" style="width:105px">' +
			'</div>' +
			'<div id="abu-process-button" class="abu-process-button " style="position: relative; overflow: hidden; direction: ltr;">' +
				'<span id="abu-process-button-text">Process Files</span>' +
				'<input type="image" name="process" class="abu-button-input" style="width:105px">' +
			'</div>' +
			'<div class="abu-options-div">' +
			((this._options.showExtractOption) ?
				'<div class="abu-options-cb" title = "Extract compressed files on upload (zip, tar, gz)"?>' +
					'<input id="extractRequestBox" type="checkbox" value="1" checked="checked">' +
					'Extract compressed files' +
				'</div>' : 
				'<div class="abu-extract-zip"><input id="extractRequestBox" type="hidden" value="1"/></div>'
			) +
			((this._options.showCloseOption) ?
				'<div class="abu-options-cb" title = "Close window upon submit and send e-mail upon completion">' +
					'<input id="closeBox" type="checkbox" value="1">' +
					'Close window upon submit' +
				'</div>' : "" 
			) +
			((this._options.showEmailOption) ?
				'<div class="abu-options-cb" title = "Send e-mail upon completion">' +
					'<input id="emailBox" type="checkbox" value="1">' +
					'Send e-mail upon completion' +
				'</div>' : "" 
			) +
			((this._options.showUpdateOption) ?
				'<div class="abu-options-cb" title = "Update existing records?">' +
					'<input id="updateBox" type="checkbox" value="1">' +
					'Update existing records?' +
				'</div>' : "" 
			) +
			((this._options.showVerboseOption) ?
				'<div class="abu-options-cb" title = "Verbose status output?">' +
					'<input id="verboseBox" type="checkbox" value="1"' +
					'Verbose status output?' +
				'</div>' : "" 
			) +
			'</div><br>' +
			'<div class="abu-list-area"><ul class="abu-upload-list"></ul>' +
				'<div class="response_text" style="display:none"></div>' +
			'</div> ' 
		); 
		$("#abu-upload-button").mouseenter(function() { $(this).addClass("abu-upload-button-hover"); });
		$("#abu-upload-button").mouseleave(function() { $(this).removeClass("abu-upload-button-hover"); });
		$("#abu-upload-button").click(function() { $("#abu-done-button").removeClass("abu-button-disabled"); });
		$("#abu-done-button").click(this._options.doneFunction);
		$("#abu-done-button").mouseenter(function() { $(this).addClass("abu-done-button-hover"); });
		$("#abu-done-button").mouseleave(function() { $(this).removeClass("abu-done-button-hover"); });
		$("#abu-process-button").click(this._options.processFunction);
		$("#abu-process-button").mouseenter(function() { $(this).addClass("abu-process-button-hover"); });
		$("#abu-process-button").mouseleave(function() { $(this).removeClass("abu-process-button-hover"); });
		$('#closeBox').change(function(){ 
			if ($('#closeBox').is(':checked')) { 
				$('#emailBox').prop('checked', true);
				$('#emailBox').attr('disabled', true);
			} else {
				$('#emailBox').attr('disabled', false);
			}
		 });

		if (this.ALLOW_DRAG_AND_DROP) {
			$(".abu-upload-drop-area").on('dragleave',function(e) { 
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = false;
						if (typeof this.timeout !== "undefined") {
							clearTimeout( this.timeout );
						}
						this.timeout = setTimeout( function(){
							if( !this.showDrag ){ 
								$(".abu-upload-drop-area").css('display','none');
								$(".abu-upload-drop-area").removeClass('abu-upload-drop-area-active');
								try { 
									e.preventDefault();
									e.stopPropogation();
								} catch(e) { /* Do nothing */ }
 							}
						}.bind(this), 200 ).bind(this);
					}
				}.bind(this)
			);
			$(".abu-upload-drop-area").on('dragover',function(e) {
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = true;
						this.activateUploadArea(e);
					}
				}.bind(this)
			);
			$(".abu-upload-drop-area").on('dragenter',function(e) {
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = true;
						this.activateUploadArea(e);
					}
				}.bind(this)
			);
			$(".abu-upload-drop-area").on('drop',function(e) {
					$(".abu-upload-drop-area").css('display','none');
					$(".abu-upload-drop-area").removeClass('abu-upload-drop-area-active');
					if(e.originalEvent.dataTransfer){
						if(e.originalEvent.dataTransfer.files.length) {
							e.preventDefault();
							e.stopPropagation();
							this.doFileUpload(e.originalEvent.dataTransfer.files);
						}   
					}
				}.bind(this)
			);
			$(this._options.element).on('dragleave',function(e) {
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = false;
						if (typeof this.timeout !== "undefined") {
							clearTimeout( this.timeout );
						}
						this.timeout = setTimeout( function(){
							if( !this.showDrag ){ 
								$(".abu-upload-drop-area").css('display','none');
								$(".abu-upload-drop-area").removeClass('abu-upload-drop-area-active');
								try { 
									e.preventDefault();
									e.stopPropogation();
								} catch(e) { /* Do nothing */ }
 							}
						}.bind(this), 200 ).bind(this);
					}
				}.bind(this)
			).bind(this);
			$(this._options.element).on('dragover',function(e) {
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = true;
						this.activateUploadArea(e);
					}
				}.bind(this)
			).bind(this);
			$(this._options.element).on('dragenter',function(e) {
					if (this.DRAG_AND_DROP_ON) {
						this.showDrag = true;
						this.activateUploadArea(e);
					}
				}.bind(this)
			);
		}	
		$("#file-upload-input").change(function(eventData) {
			this._options.uploadStartedFunction();
			this.overwriteConfirmIssued = false;
			if (typeof eventData.target.files !== 'undefined') {
				var fileA = eventData.target.files;
				if (fileA.length==0) {
					$("#abu-done-button").removeClass("abu-button-disabled");
				} 
				this.doFileUpload(fileA);
			}
		}.bind(this));
	}

	this.processingComplete = function() {
		$("#abu-done-button-text").html("Done");
		$("#abu-done-button-text").addClass("abu-done-button-done");
		$("#abu-done-button-text").removeClass("abu-done-button-cancel");
		//$("#abu-upload-button").css("display","None");
		$("#abu-process-button").addClass("abu-button-disabled");
		//$("#abu-process-button-text").html("&nbsp;");
		$("#abu-process-button").css("visibility","hidden");
		$("#abu-upload-button").addClass("abu-button-disabled");
		$("#abu-files-processing").css("display","None");
	}

	this.doFileUpload = function(fileA) {
		var start_i = $('form[id^=file-upload-form-]').length;				
		for (var i=0; i<fileA.length; i++) {
			var cFile = fileA[i];
			var adj_i = i + start_i;
			$(".abu-upload-list").append(
				'<form id="file-upload-form-' + adj_i + '" action="' + this._currentAction.replace("##FILENAME_REPLACE##",cFile.name) +
					 (($("#extractRequestBox").length>0) ? (($("#extractRequestBox").is(':checked')) ? "&extract=true" : "&extract=false") : "") +
					 (($("#emailBox").length>0) ? (($("#emailBox").is(':checked')) ? "&sendemail=true" : "&sendemail=false") : "") +
					 (($("#verboseBox").length>0) ? (($("#verboseBox").is(':checked')) ? "&verbose=true" : "&verbose=false") : "") +
					 (($("#updateBox").length>0) ? (($("#updateBox").is(':checked')) ? "&update=true" : "&update=false") : "") +
					 '" method="POST" enctype="multipart/form-data">' + 
				'</form>' + 
				'<div id="file-info-div-' + adj_i + '"><span class="abu-upload-file">' + cFile.name + '</span><span class="abu-upload-file">' +  
					" (" + ((typeof cFile.type !== 'undefined' && cFile.type !== '') ? cFile.type + ", " : '') +
					 this.bytesToSize(cFile.size) + ") </span>" +  
					'<div class="abu-progress">' +
						'<div class="abu-bar"></div >' +
						'<div class="abu-percent">0%</div >' +
					'</div>' +
					'<div id="upload-status-div-' + adj_i + '" class="abu-status"></div>' +
				'</div>');
			var formData = new FormData();
			formData.append("file" + adj_i,cFile,cFile.name);
			this.uploadFile("#file-upload-form-" + adj_i,formData);
			this.manageUploads();
		}
	}.bind(this)

	this.bytesToSize = function(bytes) {
	   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
	   if (bytes == 0) return '0 Byte';
	   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
	   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
	}

	this.activateUploadArea = function(e) {
				$(".abu-upload-drop-area").css('display','inline-block');
				$(".abu-upload-drop-area").addClass('abu-upload-drop-area-active');
				try { 
					e.preventDefault();
					e.stopPropogation();
				} catch(e) { /* Do nothing */ }
	}

	this.uploadFile = function(formSelector,formData) {
		var infoSelector = formSelector.replace("-upload-form-","-info-div-");
		var bar = $(infoSelector).find(".abu-bar");
		var percent = $(infoSelector).find(".abu-percent");
		var status = $(infoSelector).find(".abu-status");
		$(formSelector).on("submit",function(e, uploader) {
			 $(this).ajaxSubmit({
				beforeSend: function(arr, $form, options) {
					var formURL = $form.url;
					if (typeof formURL !== 'undefined' && formURL.toLowerCase().indexOf("overwrite=true")>=0 && formURL.indexOf("/files")>0) {
						// See if file already exists
						var dupURL = formURL.substring(0,formURL.indexOf("/files")+6) + "?format=json";
						this.fileName = formURL.substring(formURL.indexOf("/files")+7);
						if (this.fileName.indexOf("?")>0) {
							this.fileName = this.fileName.substring(0,this.fileName.indexOf("?"))
						}
						this.isOverwrite = false;
						this.doOverwrite = false;
						$.ajax({
							type: "GET",
							url: dupURL,
							async: false,
							dataType: 'json',
						}).done(function(data, textStatus, jqXHR) {
							//console.log(data);
							if (typeof data.ResultSet !== 'undefined' && typeof data.ResultSet.Result !== 'undefined' && Array.isArray(data.ResultSet.Result)) {
								var resultArr = data.ResultSet.Result;
								for (var i=0; i<resultArr.length; i++) {
									if (typeof resultArr[i].Name !== 'undefined' && (resultArr[i].Name == this.fileName  ||
										(typeof resultArr[i].URI !== 'undefined' && resultArr[i].URI.endsWith('/' + this.fileName)))) {
										this.isOverwrite = true;
										if (!uploader.overwriteConfirmIssued) {
											this.doOverwrite = confirm("\nDo you want to overwrite existing files?\n\n" +
													"One or more files you are uploading already exist on the sever.  Press 'OK' to overwrite files or 'Cancel' " +
													"to leave existing files in place.\n\nNOTE:  New files will still be uploaded if you choose not to " + 	
													"overwrite existing files.\n");
											uploader.doOverwrite = this.doOverwrite;
											uploader.overwriteConfirmIssued = true;
										} else {
											this.doOverwrite = uploader.doOverwrite;
										}
										break;
									}
								}
							}
						}.bind(this));
					}
					$form.data = formData;
					$form.processData=false;
					$form.contentType=false;
					status.empty();
					var percentVal = '0%';
					bar.width(percentVal)
					percent.html(percentVal);
					uploader.uploadsInProgress++;
					uploader.uploadsStarted++;
					if (this.isOverwrite && !this.doOverwrite) {
			 			status.html('<span class="abu-upload-fail">File exists.  Upload cancelled at user request.</a>');
			 			status.css("display","inline-block");
			 			$(infoSelector).find(".abu-progress").css("display","none");
						uploader.uploadsInProgress--;
						if (uploader.uploadsInProgress==0) {
							uploader._options.uploadCompletedFunction();
						}
						arr.abort();
						return false;
					} 
					return true;
				},
				uploadProgress: function(event, position, total, percentComplete) {
					var percentVal = percentComplete + '%';
					bar.width(percentVal)
					percent.html(percentVal);
				},
				error: function(result) {
					$(status).data("rtn",result);
			 		status.html('<a href="javascript:abu._fileUploader.showReturnedText(\'' + $(status).attr('id') + '\')" class="underline abu-upload-fail">Failed</a>');
			 		status.css("display","inline-block");
			 		$(infoSelector).find(".abu-progress").css("display","none");
					$("#abu-done-button").removeClass("abu-done-button-disabled");
				},
				success: function(result) {
					$(status).data("rtn",result);
					var percentVal = '100%';
					bar.width(percentVal)
					percent.html(percentVal);
					// Don't create results link if we're just returning the build path
					// check for duplicates
					var isDuplicate = false;
					try {
						var resultObj = JSON.parse(result);
						if (typeof resultObj.duplicates !== 'undefined' && resultObj.duplicates.length==1) {
							isDuplicate = true;
						} 
					} catch(e) {
						// Do nothing for now
					} 
					if (!isDuplicate) {
						if (typeof result.status !== 'undefined' || result.length > 150) {
				 			status.html('<a href="javascript:abu._fileUploader.showReturnedText(\'' + $(status).attr('id') + '\')" class="underline abu-upload-complete abu-upload-complete-text">Upload complete' + 
								((this.isOverwrite) ? ' (Existing file overwritten) ' : '') + '</a>');
						} else {
				 			status.html('<span class="abu-upload-complete abu-upload-complete-text">Upload complete' + 
								((this.isOverwrite) ? ' (Existing file overwritten) ' : '') + '</span>');
						}
						$("#abu-done-button-text").addClass("abu-done-button-file-uploaded");
					} else {
			 			status.html('<a href="javascript:abu._fileUploader.showReturnedText(\'' + $(status).attr('id') + '\')" class="underline abu-upload-fail">Duplicate file and overwrite=false.  Not uploaded.</a>');
					}
			 		status.css("display","inline-block");
			 		$(infoSelector).find(".abu-progress").css("display","none");
				},
				complete: function(xhr) {
					uploader.uploadsInProgress--;
					if (uploader.uploadsInProgress==0) {
						uploader._options.uploadCompletedFunction();
					}
					uploader.manageUploads();
				}
			}); 
			return false;
		}); 
	}

	this.showReturnedText = function(ele) {
		var eleData = $('#' + ele).data('rtn');
		xmodal.message("Server Response",((typeof eleData.status !=='undefined') ? "<h3>RETURN CODE: " + eleData.status + " (" + eleData.statusText + ")</h3><br>" +
				 eleData.responseText : eleData), undefined, {height:"400px",width:"800px"});
	}

	this.manageUploads = function() {
		var MAX_CONCURRENT_UPLOADS = this.MAX_CONCURRENT_UPLOADS;
		for (var i=1;i<=this.MAX_CONCURRENT_UPLOADS;i++) {
			var uploadsRequested = $('form[id^=file-upload-form-]').length;				
			var uploadsInProgress = this.uploadsInProgress;
			var uploadsStarted = this.uploadsStarted;
			if (uploadsInProgress < MAX_CONCURRENT_UPLOADS && uploadsStarted<uploadsRequested) {
				$("#file-upload-form-" + uploadsStarted).trigger("submit",this);
			} else if (uploadsStarted>=uploadsRequested) {
				break;
			} 
		}
	}.bind(this)

	this.uploaderHelp=function() {
		var templateV=
			'<div id="file-uploader-instructions" class="abu-uploader-instructions">' + 
			'<h3>Instructions</h3>' + 
			'<ul>' +  
			((this.ALLOW_DRAG_AND_DROP) ?
			'<li>To upload, click the <b>Upload Files</b> button or drag files into the space below the buttons. (Drag-and-drop is supported in FF, Chrome.)</li>' :
			'<li>To upload, click the <b>Upload Files</b> to begin selection of files for upload.</li>') +
			((this._options.maxFiles == 1) ?
				'<li>This uploader supports only a single file upload</li>' :
				'<li>Multiple files may be selected</li>'
			) +
			'<li>Uploads will begin automatically</li>' + 
			'<li>Upload of directories is not supported</li>' + 
			'<li>When finished uploading, press <b>Done</b> to close the modal, or, if an automation script is to be launched by this upload process, press <b>Process Files</b> to process the uploaded files.</li>' + 
			'</ul>' + 
			'</div>';
		xmodal.message("Uploader Instructions",templateV, undefined, {height:"400px",width:"800px"});
	}.bind(this)

}