(function (window, tinymce, undefined) {
	"use strict";
	
	function FileUploader (options) {
		if (!(this instanceof FileUploader)) {
			return new FileUploader(options);
		}
		
		this.opts = options;

		this.$app = document.querySelector("#app");
		this.$userfile = document.querySelector("#userfile");
		this.$upload = document.querySelector(".btn-upload");
		this.$reload = document.querySelector(".btn-reload");
		this.$truncate = document.querySelector(".btn-truncate");
		
		this.init.call(this);
		
		return this;
	}
	
	FileUploader.prototype = (function () {
		// private
		
		function load_files() {
			if (!this.$app) {
				return;
			}
			
			this.$app.innerHTML = this.opts.fu_label_loading;
			disable_btn();
			
			var qs = ["&opener=", encodeURIComponent(this.opts.opener), "&type=", encodeURIComponent(this.opts.type)].join(""),
				that = this;
			
			var $search = document.querySelector(".form-search");
			if ($search) {
				var query = $search.querySelector('input[name="q"]').value;
				if (query) {
					qs += "&q=" + encodeURIComponent(query);
				}
			}
			
			get("fileuploader.php?action=load" + qs, function (data, statusText, xhr) {
				
				that.$app.innerHTML = data;
				
				enable_btn();
				
				var cnt = xhr.getResponseHeader("X-FileUploader-Cnt");
				if (that.$truncate && cnt !== null) {
					that.$truncate.disabled = !Number(cnt);
				}
				
				[].forEach.call(that.$app.querySelectorAll(".btn-delete"), function (element, index) {
					element.addEventListener("click", function (event) {
						var el = this;
						tinymce.activeEditor.windowManager.confirm(that.opts.fu_label_del_msg, function (ok) {
							if (ok) {
								delete_file.call(that, el.dataset.name);
							}
						});
					}, false);
				});
				
				[].forEach.call(that.$app.querySelectorAll(".btn-rename"), function (element, index) {
					element.addEventListener("click", function (event) {
						var el = this;
						var name = decodeURIComponent(el.dataset.name);
						
						tinymce.activeEditor.windowManager.open({
							title: that.opts.fu_label_rename_f,
							body: [{
								type: "textbox", 
								name: "name", 
								label: that.opts.fu_label_file_name, 
								value: name.substring(0, name.lastIndexOf("."))
							}],
					        width: 340,
					        height: 90,
					        onsubmit: function(e) {
					        	if (!(e.data.name.replace(/^\s+|\s+$/g, '')).length) {
					        		return false;
					        	}
					        	var oldname = el.dataset.name;
					        	var newname = encodeURIComponent(e.data.name) + el.dataset.name.substring(el.dataset.name.lastIndexOf("."));
					        	if (oldname !== newname) {
					        		rename_file.call(that, oldname, newname);
					        	}
					        },
					        buttons: [{
					        	text: that.opts.fu_label_rename_bt,
					        	onclick: "submit"
					        }, {
					        	text: that.opts.fu_label_cancel_bt,
					        	onclick: "close"
					        }]
						});
					}, false);
				});
				
				[].forEach.call(that.$app.querySelectorAll(".btn-download"), function (element, index) {
					element.addEventListener("click", function (event) {
						
						var form = document.createElement("form");
						form.action = "fileuploader.php?action=download";
						form.method = "POST";
						form.target = "_blank";
						document.body.appendChild(form);
						
						var input = document.createElement("input");
						input.type = "hidden";
						input.name = "name";
						input.value = this.dataset.name;
						form.appendChild(input);
						
						form.submit();
						
						document.body.removeChild(form);
						
					}, false);
				});
				
				[].forEach.call(that.$app.querySelectorAll(".btn-use"), function (element, index) {
					element.addEventListener("click", function (event) {
						event.preventDefault();
						
						window.parent.postMessage({
							"sender": "fileuploader",
							"url": this.dataset.url
						});
						
					}, false);
				});
			});
		}
		
		function upload() {
			if (!this.$app) {
				return;
			}
			
			this.$app.innerHTML = this.opts.fu_label_loading;
			disable_btn();
			
			var that = this;
			
			get("fileuploader.php?action=upload", function (data) {
				that.$app.innerHTML = data;
				enable_btn();
				
				var $upload_area = that.$app.querySelector("#upload-area");
				if ($upload_area) {
					
					var $upload_title = $upload_area.querySelector("#upload-title");
					
					$upload_area.addEventListener("dragover", function (event) {
						event.preventDefault();
						event.dataTransfer.dropEffect = 'copy';
						this.classList.add("active");
					}, false);
					$upload_area.addEventListener("dragleave", function (event) {
						this.classList.remove("active");
					}, false);
					$upload_area.addEventListener("drop", function (event) {
						event.stopPropagation();
						event.preventDefault();
						event.dataTransfer.dropEffect = 'copy';
						this.classList.remove("active");
						
						if (!this.classList.contains("uploading")) {
							this.classList.add("uploading");
							
							if ($upload_title) {
								$upload_title.innerHTML = that.opts.fu_label_uploading;
							}
							
							upload_file.call(that, event.dataTransfer.files);
						}
						
					}, false);
					
					if ($upload_title) {
						$upload_title.addEventListener("click", function (event) {
							if (that.$userfile && !$upload_area.classList.contains("uploading")) {
								that.$userfile.click();
							}
						}, false);
					}
				}
			});
		}
		
		function upload_file(files) {
			var i, iCnt,
				size = 0,
				that = this,
				name = this.$userfile.name,
				fd = new FormData();
			
			for (i = 0, iCnt = files.length; i < iCnt; i += 1) {
				
				if (files[i].size > this.opts.upload_max_filesize) {
					tinymce.activeEditor.windowManager.alert(this.opts.fu_label_size_err.replace(/\{X\}/, files[i].size).replace(/\{Y\}/, this.opts.upload_max_filesize));
					return;
				}
				
				size += files[i].size;
			}
			
			if (size > this.opts.post_max_size) {
				tinymce.activeEditor.windowManager.alert(this.opts.fu_label_post_err.replace(/\{X\}/, size).replace(/\{Y\}/, this.opts.post_max_size));
				return;
			}
			
			disable_btn();
			
			for (i = 0, iCnt = files.length; i < iCnt; i += 1) {
				fd.append(name, files[i]);
			}
			
			post("fileuploader.php?action=upload", function (data) {
				
				that.$userfile.form.reset();
				
				if (data && data.status && data.status === "OK") {
					load_files.call(that);
				} else {
					enable_btn();
					if (data.text) {
						tinymce.activeEditor.windowManager.alert(data.text);
					}
				}
		
			}, fd);
		}
		
		function delete_file(name) {
			var that = this,
				fd = new FormData();
			
			fd.append("name", name);
			
			post("fileuploader.php?action=delete", function (data) {
				
				if (data && data.status && data.status === "OK") {
					load_files.call(that);
				} else {
					if (data.text) {
						tinymce.activeEditor.windowManager.alert(data.text);
					}
				}
				
			}, fd);
		}
		
		function rename_file(from, to) {
			var that = this,
				fd = new FormData();
			
			fd.append("from", from);
			fd.append("to", to);
			
			post("fileuploader.php?action=rename", function (data) {
				
				if (data && data.status && data.status === "OK") {
					load_files.call(that);
				} else {
					if (data.text) {
						tinymce.activeEditor.windowManager.alert(data.text);
					}
				}
				
			}, fd);
		}
		
		function truncate() {
			var that = this;
			
			disable_btn();
			
			post("fileuploader.php?action=truncate", function (data) {
				if (data && data.status && data.status === "OK") {
					load_files.call(that);
				} else {
					enable_btn();
					if (data.text) {
						tinymce.activeEditor.windowManager.alert(data.text);
					}
				}
			});
		}
		
		function disable_btn() {
			[].forEach.call(document.querySelectorAll(".btn"), function (element) {
				element.disabled = true;
			});
		}
		
		function enable_btn() {
			[].forEach.call(document.querySelectorAll(".btn"), function (element) {
				element.disabled = false;
			});
		}
		
		function main_events() {
			var that = this;
			
			if (this.$userfile) {
				this.$userfile.addEventListener("change", function (event) {
					var $upload_area = document.querySelector("#upload-area");
					if ($upload_area) {
						$upload_area.classList.add("uploading");
					}
					var $upload_title = document.querySelector("#upload-title");
					if ($upload_title) {
						$upload_title.innerHTML = that.opts.fu_label_uploading;
					}
					upload_file.call(that, this.files);
				}, false);
			}
			
			if (this.$upload) {
				this.$upload.addEventListener("click", function (event) {
					upload.call(that);
				}, false);
			}
			
			if (this.$reload) {
				this.$reload.addEventListener("click", function (event) {
					load_files.call(that);
				}, false);
			}
			
			if (this.$truncate) {
				this.$truncate.addEventListener("click", function (event) {
					tinymce.activeEditor.windowManager.confirm(that.opts.fu_label_trunc_msg, function (ok) {
						if (ok) {
							truncate.call(that);
						}
					});
				}, false);
			}
			
			var $search = document.querySelector(".form-search");
			if ($search) {
				$search.addEventListener("submit", function (event) {
					event.preventDefault();
					load_files.call(that);
					return false;
				}, false);
			}
		}
		
		function get(url, callback) {
			var xhr = new XMLHttpRequest();
			xhr.open("GET", url, true);
			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			xhr.onload = function () {
				onLoad.call(null, xhr, callback);
			};
			xhr.send(null);
		}
		
		function post(url, callback, data) {
			var xhr = new XMLHttpRequest();
			xhr.open("POST", url, true);
			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			xhr.onload = function () {
				onLoad.call(null, xhr, callback);
			};
			xhr.send(data);
		}
		
		function onLoad(xhr, callback) {
			if (xhr.readyState === 4) {
				var data;
				if (/application\/json/i.test(xhr.getResponseHeader("content-type"))) {
					data = JSON.parse(xhr.responseText);
				} else {
					data = xhr.responseText;
				}
			
				if (typeof callback === "function") {
					callback.call(null, data, xhr.statusText, xhr);
				}
			}
		}
		
		// public
		return {
			init: function () {
				main_events.call(this);
				load_files.call(this);
			}
		};
		
	})();
	
	return (window.pjFileUploader = FileUploader);  
	
})(window, window.parent.tinymce);