
Ext.define("Ext.ux.plugin.UploadDD", {

	alias: ["plugin.uploadDD"],

	extend: "Ext.AbstractPlugin",

	statics: {
		mime: {
			"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
			"application/vnd.openxmlformats-officedocument.spreadsheetml.template": "xltx",
			"application/vnd.openxmlformats-officedocument.presentationml.template": "potx",
			"application/vnd.openxmlformats-officedocument.presentationml.slideshow": "ppsx",
			"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
			"application/vnd.openxmlformats-officedocument.presentationml.slide": "sldx",
			"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
			"application/vnd.openxmlformats-officedocument.wordprocessingml.template": "dotx",
			"application/vnd.ms-excel.addin.macroEnabled.12": "xlam",
			"application/vnd.ms-excel.sheet.binary.macroEnabled.12": "xlsb",
			"application/envoy": "evy",
			"application/fractals": "fif",
			"application/futuresplash": "spl",
			"application/hta": "hta",
			"application/internet-property-stream": "acx",
			"application/mac-binhex40": "hqx",
			"application/msword": "doc",
			"application/msword": "dot",
			"application/oda": "oda",
			"application/olescript": "axs",
			"application/pdf": "pdf",
			"application/pics-rules": "prf",
			"application/pkcs10": "p10",
			"application/pkix-crl": "crl",
			"application/postscript": "ai",
			"application/postscript": "eps",
			"application/postscript": "ps",
			"application/rtf": "rtf",
			"application/set-payment-initiation": "setpay",
			"application/set-registration-initiation": "setreg",
			"application/vnd.ms-excel": "xla",
			"application/vnd.ms-excel": "xlc",
			"application/vnd.ms-excel": "xlm",
			"application/vnd.ms-excel": "xls",
			"application/vnd.ms-excel": "xlt",
			"application/vnd.ms-excel": "xlw",
			"application/vnd.ms-outlook": "msg",
			"application/vnd.ms-pkicertstore": "sst",
			"application/vnd.ms-pkiseccat": "cat",
			"application/vnd.ms-pkistl": "stl",
			"application/vnd.ms-powerpoint": "pot",
			"application/vnd.ms-powerpoint": "pps",
			"application/vnd.ms-powerpoint": "ppt",
			"application/vnd.ms-project": "mpp",
			"application/vnd.ms-works": "wcm",
			"application/vnd.ms-works": "wdb",
			"application/vnd.ms-works": "wks",
			"application/vnd.ms-works": "wps",
			"application/winhlp": "hlp",
			"application/x-bcpio": "bcpio",
			"application/x-cdf": "cdf",
			"application/x-compress": "z",
			"application/x-compressed": "tgz",
			"application/x-cpio": "cpio",
			"application/x-csh": "csh",
			"application/x-director": "dcr",
			"application/x-director": "dir",
			"application/x-director": "dxr",
			"application/x-dvi": "dvi",
			"application/x-gtar": "gtar",
			"application/x-gzip": "gz",
			"application/x-hdf": "hdf",
			"application/x-internet-signup": "ins",
			"application/x-internet-signup": "isp",
			"application/x-iphone": "iii",
			"application/x-javascript": "js",
			"application/x-latex": "latex",
			"application/x-msaccess": "mdb",
			"application/x-mscardfile": "crd",
			"application/x-msclip": "clp",
			"application/x-msdownload": "dll",
			"application/x-msmediaview": "m13",
			"application/x-msmediaview": "m14",
			"application/x-msmediaview": "mvb",
			"application/x-msmetafile": "wmf",
			"application/x-msmoney": "mny",
			"application/x-mspublisher": "pub",
			"application/x-msschedule": "scd",
			"application/x-msterminal": "trm",
			"application/x-mswrite": "wri",
			"application/x-netcdf": "cdf",
			"application/x-netcdf": "nc",
			"application/x-perfmon": "pma",
			"application/x-perfmon": "pmc",
			"application/x-perfmon": "pml",
			"application/x-perfmon": "pmr",
			"application/x-perfmon": "pmw",
			"application/x-pkcs12": "p12",
			"application/x-pkcs12": "pfx",
			"application/x-pkcs7-certificates": "p7b",
			"application/x-pkcs7-certificates": "spc",
			"application/x-pkcs7-certreqresp": "p7r",
			"application/x-pkcs7-mime": "p7c",
			"application/x-pkcs7-mime": "p7m",
			"application/x-pkcs7-signature": "p7s",
			"application/x-sh": "sh",
			"application/x-shar": "shar",
			"application/x-shockwave-flash": "swf",
			"application/x-stuffit": "sit",
			"application/x-sv4cpio": "sv4cpio",
			"application/x-sv4crc": "sv4crc",
			"application/x-tar": "tar",
			"application/x-tcl": "tcl",
			"application/x-tex": "tex",
			"application/x-texinfo": "texi",
			"application/x-texinfo": "texinfo",
			"application/x-troff": "roff",
			"application/x-troff": "t",
			"application/x-troff": "tr",
			"application/x-troff-man": "man",
			"application/x-troff-me": "me",
			"application/x-troff-ms": "ms",
			"application/x-ustar": "ustar",
			"application/x-wais-source": "src",
			"application/x-x509-ca-cert": "cer",
			"application/x-x509-ca-cert": "crt",
			"application/x-x509-ca-cert": "der",
			"application/ynd.ms-pkipko": "pko",
			"application/zip": "zip",
			"application/acad": "dwg",
			"application/step": "stp",
			"image/pjpeg": "jpeg",
			"image/jpeg": "jpeg",
			"image/jpg": "jpg",
			"image/png": "png",
			"image/gif": "gif",
			"image/tiff": "tiff",
			"image/x-tiff": "tiff"
		},
		mimeToExtension: function (s_mime) {
			return Ext.ux.plugin.UploadDD.mime[s_mime];
		},
		extensionToMime: function (s_extension) {
			var s_mime;
			Ext.Object.each(Ext.ux.plugin.UploadDD.mime, function (s_key, s_name) {
				if (s_name == s_extension) {
					s_mime = s_key;
				}
			});
			return s_mime;
		},
		cancelEvent: function (o_event) {

			o_event = o_event || window.event;

			if (o_event.preventDefault) {
				o_event.preventDefault();
			}

			if (o_event.stopPropagation) {
				o_event.stopPropagation();
			}

			return false;
		},
		addEventHandler: function (obj, evt, handler) {

			if (obj.addEventListener) {
				// W3C method
				obj.addEventListener(evt, handler, false);
			}
			else if (obj.attachEvent) {
				// IE method.
				obj.attachEvent("on" + evt, handler);
			}
			else {
				// Old school method.
				obj["on" + evt] = handler;
			}
		}
	},

	/**
	 * @cfg {Array} [extensions=null]
	 * Array of extensions allowed to drop. If null then all extensions are allowed
	 */
	extensions: null,

	/**
	 * @private {Boolean} enableDrop
	 * False to disallow the View from accepting drop gestures.
	 */
	enableDrop: true,

	pluginId: "uploadDD",

	baseCls: "x-ux-plugin-uploadDD",
	failureCls: "x-ux-plugin-uploadDD-error",
	successCls: "x-ux-plugin-uploadDD-over",
	dragging: 0,

	_filePreviewMap: null,

	init: function(i_component) {

		var i_plugin = this;
		var i_el = i_component.getEl();

		i_plugin.component = i_component;

		i_component.addCls(i_plugin.baseCls);

		if (i_el && i_el.dom && i_el.query("table")[0]) {
			i_plugin.initUploadDD(i_el.query("table")[0]);
		}
		else {
			i_component.on("afterrender", function (i_self) {
				i_plugin.initUploadDD(i_self.getEl().query("table")[0]);
			}, i_component, { single: true });
		}

		return i_plugin;
	},

	initUploadDD: function(i_dropNode) {

		var i_plugin = this;
		var i_component = i_plugin.component;
		var i_class = Ext.ux.plugin.UploadDD;
		var i_global = Ext.global;

		if (i_global.FileReader) {

			// Prevent drops on body
			i_class.addEventHandler(document.body, "dragenter", function(o_event) {
				i_plugin.onBodyEnter(o_event);
			});

			i_class.addEventHandler(document.body, "dragleave", function(o_event) {
				i_plugin.onBodyLeave(o_event);
			});

			i_class.addEventHandler(document.body, "dragover", Ext.ux.plugin.UploadDD.cancelEvent);
			i_class.addEventHandler(document.body, "drop", function(o_event) {
				i_plugin.cancelDropEvent(o_event);
			});

			// Tells the browser that we *can* drop on this target
			i_class.addEventHandler(i_dropNode, "dragover", Ext.ux.plugin.UploadDD.cancelEvent);

			i_class.addEventHandler(i_dropNode, "dragenter", function (o_event) {
				i_plugin.onDragEnter(o_event);
			});

			i_class.addEventHandler(i_dropNode, "dragleave", function (o_event) {
				i_plugin.onDragLeave(o_event);
			});

			i_class.addEventHandler(i_dropNode, "drop", function (o_event) {
				i_plugin.onDragDrop(o_event);
			});
		}

		// Hide this component since no DnD upload is possible
		// TODO: Give component a chance to do this instead - plugins don"t decide, they tell!
		else {
			i_component.hide();
		}
	},

	cancelDropEvent: function(o_event) {
		var i_plugin = this;
		var i_component = i_plugin.component;
		o_event = o_event || window.event;

		if (o_event.preventDefault) {
			o_event.preventDefault();
		}

		if (o_event.stopPropagation) {
			o_event.stopPropagation();
		}
		i_plugin.dragging = 0;
		i_component.fireEvent("bodydragleave", i_component, o_event);

		return false;
	},

	onBodyEnter: function(o_event) {
		var i_plugin = this;
		var i_component = i_plugin.component;
		i_plugin.dragging++;
		o_event.dataTransfer.dropEffect = "copy";
		i_component.fireEvent("bodydragenter", i_component, o_event);
	},

	onBodyLeave: function(o_event) {
		var i_plugin = this;
		var i_component = i_plugin.component;
		i_plugin.dragging--;
		if (i_plugin.dragging === 0) {
			i_component.fireEvent("bodydragleave", i_component, o_event);
		}
	},

	onDragEnter: function (o_event) {

		var i_plugin = this;
		var i_component = i_plugin.component;
		var i_transfer = o_event.dataTransfer;
		var b_allow = true;

		//Ext.ux.plugin.UploadDD.cancelEvent(o_event);

		// Extensions overloading, in case it is a comma seperated string
		// we strip whitespaces and split on comma
		var a_extensions = i_plugin.extensions;

		if (ip2.isString(a_extensions)) {
			a_extensions = a_extensions.replace(" ", "");
			a_extensions = a_extensions.split(",");
		}

		if (a_extensions[0] != "*") {
			ip2.each(i_transfer.items, function (o_item) {
				if (!ip2.isNumber(o_item)) {
					var s_extension = i_plugin.getRewriter().mimeToExtension(o_item.type);
					b_allow = (Ext.Array.indexOf(a_extensions, s_extension) > -1);
				}
			});
		}

		if (!b_allow) {
			i_component.addCls(i_plugin.failureCls);
			i_plugin.enableDrop = false;
		}
		else {
			i_component.addCls(i_plugin.successCls);
			i_plugin.enableDrop = true;
		}

		i_component.fireEvent("dragenter", i_component, o_event);
	},

	onDragLeave: function (o_event) {

		var i_plugin = this;
		var i_component = i_plugin.component;

		//Ext.ux.plugin.UploadDD.cancelEvent(o_event);

		i_component.removeCls(i_plugin.successCls);
		i_component.removeCls(i_plugin.failureCls);

		i_component.fireEvent("dragleave", i_component, o_event);
	},

	onDragDrop: function (o_event) {

		var i_plugin = this;
		var i_component = i_plugin.component;

		// get window.event if e argument missing (in IE)
		o_event = o_event || Ext.global.event;

		//Ext.ux.plugin.UploadDD.cancelEvent(o_event);

		// TODO ADD BEFORE DROP HANDLER
		if (i_plugin.enableDrop) {

			var i_transfer = o_event.dataTransfer;
			var i_files = i_transfer.files || [];

			var a_result = i_files;

			if (Ext.isIE) {

				var a_files = [];

				for (var i = 0; i < i_files.length; i++) {
					var i_file = i_files.item(i);
					a_files.push(i_file);
				}

				a_result = a_files;
			}

			var b_beforedrop = i_component.fireEvent("beforedrop", i_component, a_result, o_event);

			if (b_beforedrop !== false) {
				i_component.fireEvent("drop", i_component, a_result);
			}
		}

		i_component.removeCls(i_plugin.failureCls);
		i_component.removeCls(i_plugin.successCls);

		return false;
	},

	getExtensions: function () {

		return this.extensions;
	},
	setExtensions: function (a_extensions) {

		this.extensions = a_extensions;
		return this;
	},

	getRewriter: function () {

		var i_plugin = this;
		var s_class = i_plugin.$className;
		var i_global = Ext.global;

		return ip2.getProperty(s_class, i_global);
	}
});
