var emp = emp || {};


// TODO presunut to do emp.js
emp.uploader = new (function() {

	var uploaders = [];


	function Upload(data) {
		var self = this;

		var data = $.extend({
			file: null,
			url: "medial/upload",
			path: "/",
			onComplete: function() { },
			onProgress: function(progress) { }
		}, data);

		this.getFileObject = function() {
			return data.file;
		}

		this.getUplaoder = function() {
			return data.uplaoder;
		}

		this.setUrl = function(url) {
			data.url = url;
		}

		this.getUrl = function() {
			return data.url;
		}

		this.setPath = function(path) {
			data.path = path;
		}

		this.getPath = function() {
			return data.path;
		}

		this.setOnProgress = function(callback) {
			if (typeof callback == "function")
				data.onProgress = callback;
		}

		this.onProgress = function(progress) {
			data.onProgress(progress, self);
		}

		this.setOnComplete = function(callback) {
			if (typeof callback == "function")
				data.onComplete = callback;
		}

		this.onComplete = function(response) {
			data.onComplete(response, self);
		}

		this.xhr = null;

	}


	function Uploader(o) {
		var self = this;

		var o = $.extend({
			target: $(),
			onSelect: function(upload, self) {  },
			onStart: function(self) {  },
			onComplete: function(self) {  },
			onError: function(self) {  }
		}, o);

		var queue = [];



		function init() {

			var launchButton = $('<div>')
				.addClass(o.target.attr("class"))
				.css({
					position: "relative",
					overflow: "hidden"
				});

			o.target.replaceWith(launchButton);

			launchButton.append(
				o.target.html(),
				$('<input type="file" multiple="true">')
					.css({width: 500, height: 500, position: "absolute", top: -100, right: 0})
					.change(function() {
						uploadFiles(this.files);
					})
			)

		}


		function startUpload() {

			if (!queue.length || !emp.locker.lock(self))
				return;

			var upload = queue.shift();

			encodedFileName = encodeURIComponent(upload.getFileObject().fileName);

			upload.xhr = new XMLHttpRequest();

			upload.xhr.upload.onprogress = function(e) {
				if (e.lengthComputable)
					upload.onProgress(e.loaded / e.total);
			};

			upload.xhr.onreadystatechange = function() {
				if (this.readyState == 4) {
					upload.onComplete($.parseJSON(this.responseText)); //todo: overit
					emp.locker.unlock(self);

					if (queue.length)
						startUpload();
					else
						o.onComplete(self);
				}
			}

			upload.xhr.open("POST", upload.getUrl() + "?file=" + encodedFileName + "&path=" + upload.getPath());
			upload.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			upload.xhr.setRequestHeader("X-File-Name", encodedFileName);
			upload.xhr.setRequestHeader("Content-Type", "application/octet-stream");
			upload.xhr.send(upload.getFileObject());

			o.onStart(self, upload);

		}


		function uploadFiles(files) {

			if (!files.length)
				return;

			for (var i = 0; i < files.length; i++) {
				var upload = new Upload({
					file: files[i],
					uploader: self
				})

				o.onSelect(upload, self);
				queue.push(upload);
			}

			startUpload();
		}


		this.isUploading = function() {
			return emp.locker.locked(self);
		}


		init();

	}


	this.create = function(o) {
		var upload = new Uploader(o)
		uploaders.push(upload);

		return upload;
	}


})();



emp.medialInput = new (function() {

	var MedialInput = function(o) {

		var self = this;
		var o = $.extend({
			name: "",
			holder: $(),
			multipleFiles: false,
			fileFilter: false,
			value: null
		}, o);


		var elements = {
			holder: $('<span>'),
			addFiles: $('<a href="#add-files" class="emp-medial-input add-files">')
		}


		function init() {
			elements.holder.appendTo(o.holder);

			elements.addFiles.appendTo(o.holder).append('<span><span>+</span>Pridať súbory</span>').click(function() {
				emp.fileManager.open({
					fileFilter: o.fileFilter,
					multipleFiles: o.multipleFiles,
					onSelect: function(file) {
						self.insertFile(file.path);
					}
				});

				return false;
			});

			if (o.value)
				$.each(o.value.split(","), function() {
					self.insertFile(this);
				})
		}


		this.insertFile = function(filePath) {
			var element;

			if (elements.holder.find('input[value="' + filePath + '"]').length)
				return;

			element = $('<div class="emp-medial-input">')
				.appendTo(elements.holder)
				.append(
					$('<input type="hidden" name="' + o.name + '[]" value="' + filePath + '" />'),
					$('<img src="medial/thumb?size=medial-thumb&file=' + filePath + '" alt="' + filePath.replace(/(.*\/)/, "") + '" />'),
					$('<a href="#delete" class="emp-icon emp-icon-delete">').click(function() {
						element.remove();
						elements.addFiles.appendTo(o.holder);
						return false;
					})
				);
			
			if (!o.multipleFiles)
				elements.addFiles.detach();
		}


		init();

	}


	this.create = function(o) {
		return new MedialInput(o);
	}

})();




emp.medial = new (function() {

	var self = this;


	this.createInput = function(name, value) {
		$('<a href="#add-files" class="emp-medial-input add-files">')
			.appendTo($('.-js-medial-holder-' + name))
			.append(
				$('<span>').append(
					$('<span>').append("+"),
					"pridať súbory"
				)
			).click(function() {
				emp.fileManager.open({
					onSelect: function(file) {
						self.insertFile(name, file.path);
					}
				});

				return false;
			});

			if (value)
				$.each(value.split(","), function() {
					self.insertFile(name, this);
				})
	}


	this.insertFile = function(name, path) {
		var holder = $('.-js-medial-holder-' + name);
		var element;

		if (holder.find('input[value="' + path + '"]').length)
			return;

		element = $('<div class="emp-medial-input">')
			.insertBefore(holder.find(".add-files"))
			.append(
				$('<input type="hidden" name="' + name + '[]" value="' + path + '" />'),
				$('<img src="medial/thumb?file=' + path + '&size=medial-thumb" alt="' + path.replace(/(.*\/)/, "") + '" />'),
				$('<a href="#delete" class="emp-icon emp-icon-delete">').click(function() {
					element.remove();
					return false;
				})
			);
	}

});



emp.fileManager = new (function() {

	var elements = $('<div class="directories-frame">');
	var buttons = $('<div>');
	var dialog;

	var cache = {};
	var directories = [];
	var uploads = [];
	var selectedFile = [];
	var filter;
	var order = "extension";
	var uploader;
	var selectable;
	var multipleFiles;


	function File(fileData) {

		var self = this;
		var fileElement = $('<tr class="file">')


		function init() {

			fileElement.append(
				$('<td>').append(
					$('<span class="emp-file-icon">').addClass("emp-file-icon-" + (self.isUpload() ? "upload" : fileData.type)),
					$('<span class="filename">').attr("title", fileData.filename + (fileData.extension ? "." + fileData.extension : "") ).append(
						fileData.filename.substr(0,32) + ( fileData.filename.length > 32 ? "..." : "" ) +
						(fileData.extension ? "." + fileData.extension : "")
					)
				)
			)

			if (self.isUpload()) {

				fileElement.append(
					$('<td>').attr({colspan: 2}).append(
						$('<span class="uploading-progress-bar">').append(
							fileElement.items().progress = $('<span class="progress">')
						)
					),
					$('<td class="small" align="right">').append(
						$('<a class="emp-icon emp-icon-delete">').click(function() {
							fileData.upload.xhr.abort();
							return false;
						})
					)
				)

			} else {

				fileElement.append(
					$('<td class="small">').append(self.isDirectory() ? '&nbsp;' : formatFileSize(fileData.size)),
					$('<td class="small">').append(fileData.modified),
					$('<td class="small" align="right">').append(
						$('<a class="emp-icon emp-icon-edit hidden">').click(function() {
							renameFile(self);
							return false;
						}),
						$('<a class="emp-icon emp-icon-delete hidden">').click(function() {
							deleteFile(self);
							return false;
						})
					)
				);
			}

			if (fileData.justUploaded)
				fileElement.addClass("just-uploaded");

			if (!self.checkFilter())
				fileElement.addClass("filtered");

			fileElement.click(function(e) {
				if (self.isDirectory()) {
					openDirectory(fileData.path);
					self.select();
				} else {
					if (!fileData.uploading && self.checkFilter())
						selectFile(self);
				}

				return false;
			})
		}


		this.getElement = function() {
			return fileElement;
		}


		this.getData = function() {
			return fileData;
		}


		this.isDirectory = function() {
			return fileData.type == "folder";
		}


		this.isUpload = function() {
			return fileData.upload ? true : false;
		}


		this.checkFilter = function() {
			return filter ? filter.indexOf(fileData.extension) > -1 : true;
		}


		this.remove = function() {
			fileElement.remove();
			delete this;
		}


		this.select = function() {
			fileElement.addClass("selected");
		}


		this.deselect = function() {
			fileElement.removeClass("selected");
		}


		this.updateFile = function(newFileData) {
			fileData = newFileData;
			fileElement.empty();
			init();
		}


		init();

	}


	function Directory(path, data) {

		var self = this;
		var files = [];

		this.path = path;

		var directoryElement = $('<div class="directory">');

		function init() {
			directoryElement.append(
				$('<table cellspacing="0" cellpadding="0" border="0">').append(
					$('<thead>').append(
						$('<tr>').append(
							$('<th class="col-filename">'),
							$('<th class="col-filesize">'),
							$('<th class="col-modified">'),
							$('<th class="col-options">')
						)
					),
					directoryElement.items().files = $('<tbody>')
				),
				$('<span class="retriever">').click(function() {
					openDirectory(path);
				})
			);

			directoryElement.appendTo(elements.items().directories);

			for (var i = 0; i < data.length; i++)
				self.insertFile(data[i]);

			self.renderDirectory();
		}


		this.insertFile = function(fileData) {
			var file = new File($.extend(fileData, {directory: self}));

			files.push(file);

			return file;
		}


		this.removeFile = function(fileObject) {
			files.removeItem(fileObject);
			fileObject.remove();
		}


		this.renderDirectory = function(orderBy, direction) {

			if (!files.length) {
				$('<div class="empty-directory">').append("Adresár je prázdny").appendTo(directoryElement.items().files);
				return;
			} else {
				directoryElement.items().files.find('.empty-directory').remove();
			}


			if (orderBy)
				order = orderBy;

			var prepareValue = function(object, key) {
				var value = object.getData()[key]; //todo pokus

				if (value instanceof String)
					value = value.removeAccents().toLowerCase();

				return value;
			}

			files.sort(function(a, b) {
				if (a.isDirectory() - b.isDirectory() != 0)
					return a.isDirectory() ? -1 : 1

				if (a.isDirectory() && b.isDirectory())
					result = prepareValue(a, "basename") > prepareValue(b, "basename");
				else
					if (prepareValue(a, orderBy) == prepareValue(b, orderBy))
						result = prepareValue(a, "basename") > prepareValue(b, "basename")
					else
						result = prepareValue(a, orderBy) > prepareValue(b, orderBy)

				return result * ( direction == "desc" ? -1 : 1 );

			});

			// fixme: tbody
			for (var i = 0; i < files.length; i++)
				directoryElement.items().files.append(files[i].getElement());

			selectFile();

		}


		this.collapse = function() {
			directoryElement.addClass("collapsed");
			return this;
		}


		this.uncollapse = function() {
			directoryElement.removeClass("collapsed");
			return this
		}


		this.hide = function() {
			directoryElement.addClass("hidden");
			return this;
		}


		this.unhide = function() {
			directoryElement.removeClass("hidden");
			return this;
		}


		this.removeSelection = function() {
			directoryElement.find(".selected").removeClass("selected");
		}


		this.close = function() {
			directoryElement.remove();
		}


		this.getPath = function() {
			return path;
		}


		this.getFiles = function() {
			return files;
		}


		this.getElement = function() {
			return directoryElement;
		}


		init();

	}


	function getFileType(extension) {
			return "file";
		}


	function renameFile(fileObject) {

		var dialog;
		var form = $('<form class="emp-form">')

		function renameFileCallback() {
			name = $.trim(form.items().input.val());

			if (name.length) {

				if (name == fileObject.getData().filename) {

					dialog.close();

				} else {

					emp.loader.show();

					$.post("medial/rename-file", {path: fileObject.getData().path, name: name}, function(response) {
						emp.loader.hide();

						fileObject.updateFile(response);
						getCurrentDirectory().renderDirectory();

						dialog.close();
					}, "json");

				}
			}
		}

		form.append(
			$('<div class="input-field">')
				.append(
					$('<label>').html("Názov položky"),
					form.items().input = $('<input type="text">')
						.val(fileObject.getData().filename)
				)
		)

		form.submit(function() {
			renameFileCallback();
			return false;
		})


		dialog = emp.dialog.open({
			title: "Správca súborov",
			content: form,
			focus: form.items().input,
			buttons: {"Premenovať": true, "Zrušiť": false},
			onSubmit: function() {
				renameFileCallback();
				return false;
			}
		})
	}


	function deleteFile(fileObject) {

		function deleteCallback() {
			emp.loader.show();

			$.post("medial/delete-file", {path: fileObject.getData().path}, function(response) {
				emp.loader.hide();

				getCurrentDirectory().removeFile(fileObject);
				getCurrentDirectory().renderDirectory();
			});
		}

		emp.dialog.open({
			title: "Správca súborov",
			content: "Naozaj mám odstrániť súbor <b>" + fileObject.getData().basename + "</b> ?",
			buttons: {"Odstrániť": true, "Zrušit": false},
			onSubmit: function(dialog) {
				if (fileObject.isDirectory()) {
					emp.dialog.open({
						title: "Správca súborov",
						content: '<b>' + fileObject.getData().basename + '</b> je adresár a možno obsahuje ďalšie súbory.<br/> Naozaj ho mám odstrániť?',
						buttons: {"Naozaj odstrániť": true, "Zrušit": false},
						onSubmit: function() {
							deleteCallback();
						}
					})
				} else {
					deleteCallback();
				}
			}
		})
	}


	function insertUpload(upload) {
		var file = getCurrentDirectory().insertFile({
			filename: upload.getFileObject().name,
			size: upload.getFileObject().size,
			upload: upload
		});

		upload.setPath(getCurrentDirectory().getPath());

		upload.setOnProgress(function(progress) {
			file.getElement().items().progress.css({width: Math.round(progress * 100) + "%"})
		})

		upload.setOnComplete(function(response) {
			getCurrentDirectory().removeFile(file);

			if (response)
				getCurrentDirectory().insertFile($.extend(response, {justUploaded: true}));

			getCurrentDirectory().renderDirectory();
		});

		getCurrentDirectory().renderDirectory();

	}


	function createDirectory() {

		var dialog;
		var form = $('<form class="emp-form">');

		function createDirectoryCallback() {
			name = $.trim(form.items().input.val());

			if (name.length) {
				emp.loader.show();

				$.post("medial/create-directory", {name: name, path: getCurrentDirectory().getPath()}, function(response) {
					emp.loader.hide();

					getCurrentDirectory().insertFile(response);
					getCurrentDirectory().renderDirectory();

					dialog.close();
				}, "json");
			}
		}

		form.append(
			$('<div class="input-field">')
				.append(
					$('<label>').html("Názov adresára"),
					form.items().input = $('<input type="text">')
				)
			)

		form.submit(function() {
			createDirectoryCallback();
			return false;
		})

		dialog = emp.dialog.open({
			title: "Správca súborov",
			content: form,
			focus: form.items().input,
			buttons: {"Vytvoriť": true, "Zrušiť": false},
			onSubmit: function() {
				createDirectoryCallback();
				return false;
			}
		})

	}


	function getCurrentDirectory() {
		return directories.length ? directories[directories.length - 1] : null;
	}


	function openDirectory(path, force) {

		function openingCallback(data) {

			var founded = false;

			for (var i = 0; i < directories.length; i++)
				if (directories[i].getPath() == path)
					founded = i;

			if (founded !== false) {

				var newDirectories = directories.splice(0, founded + 1);

				for (var i = 0; i < directories.length; i++)
					directories[i].close();

				directories = newDirectories;

			} else {

				directories.push(new Directory(path, data));

			}

			for (var i = 0; i < directories.length - 2; i++)
				directories[i].hide();

			if (directories.length > 1)
				directories[directories.length - 2].unhide().collapse();

			directories[directories.length - 1].unhide().uncollapse().removeSelection();

		}

		if (!force && cache[path])
			openingCallback(cache[path]);
		else
			$.post("medial/open-directory", {ajax: true, path:path}, function(response) {
				cache[path] = response;
				openingCallback(response);
			}, "json");

	}


	function selectFile(fileObject, add) {
		if (!selectable)
			return;

		if (!fileObject) {
			selectedFile = []
			$.each(selectedFile, function() {this.deselect()})
		} else {
			if (selectedFile.removeItem(fileObject)) {
				fileObject.deselect();
			} else {
				fileObject.select();
				selectedFile.push(fileObject);
			}
		}

		if (selectedFile.length)
			buttons.items().select.enable();
		else
			buttons.items().select.disable();

	}


	function formatFileSize(size) {
		var i = 0;

		while ((a = size / 1024) > 1) {
			size = a;
			i++;
		}

		return size.toFixed(i ? 1 : 0) + " " + ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][i];
	}


	function init() {
		elements.append(
			elements.items().directories = $('<div class="directories">'),
			elements.items().details = $('<div class="details">')
		);

		buttons.append(
			buttons.items().upload = $('<button class="emp-button fl">').html("Nahrať súbory"),
			buttons.items().options = $('<button class="emp-button fl " style="margin-left:-5px; min-width: 20px; padding: 0 5px">').html('<span class="emp-icon emp-icon-dark-gear" style="margin: 0"></span>').click(function() {

			}),
			buttons.items().directory = $('<button class="emp-button fl">').html("Nový adresár").click(function() {
				createDirectory();
			}),
			buttons.items().select = $('<button class="emp-button hot">').disable().html("Vybrať súbor").click(function() {
				dialog.submit();
			}),
			buttons.items().close = $('<button class="emp-button">').html("Zavrieť").click(function() {
				dialog.cancel();
			})
		);

		uploader = emp.uploader.create({
			target: buttons.items().upload,
			multiple: true,
			onSelect: function(upload) {insertUpload(upload)}
		});

	}


	this.open = function(o) {

		o = $.extend({
			path: "/",
			filter: null,
			multipleFiles: false,
			onSelect: null
		}, o);

		directories = []
		cache = {}

		elements.items().directories.empty();
		openDirectory(o.path);

		selectable = typeof o.onSelect == "function";
		multipleFiles = o.multipleFiles;

		if (!selectable)
			buttons.items().select.hide();
		else
			buttons.items().select.show();

		if (typeof o.filter == "string") {
			switch (o.filter) {
				case "images": case "image":filter = ["jpg", "jpeg", "gif", "png", "bmp", "tiff"];break;
				default:filter = null;
			}
		} else {
			filter = o.filter;
		}

		dialog = emp.dialog.open({
			title: "Správca súborov",
			content: elements,
			buttons: buttons,
			focus: false,
			css: "emp-file-manager",
			onSubmit: function() {
				if (uploader.isUploading())
					return false;

				$.each(selectedFile, function() {
					o.onSelect(this.getData())
				})
			},
			onCancel: function() {
				if (uploader.isUploading())
					return false;
			}
		})

	}


	init();

})();


