/**
 * jQuery serializeObject
 * Serializes a form (or a set of inputs) to an object. It uses FileReader and Deferred to serialize input[type="file"]
 * @returns {jQuery.Deferred} deferred object
 * @requires jQuery 1.5+
 * @requires FileReader JavaScript API
 * @author Aleksandr.ru
 * @link http://aleksandr.ru
 * 
 * @link http://stackoverflow.com/questions/1184624/convert-form-data-to-javascript-object-with-jquery
 * @link https://www.html5rocks.com/ru/tutorials/file/dndfiles/
 * @link http://stackoverflow.com/questions/6978156/get-base64-encode-file-data-from-input-form
 */
;(function($) {
	if (window.File && window.FileReader && window.FileList && $.Deferred)
	$.fn.serializeObject = function() {
		var $form = $(this);
		return $.when().then(function() {
			var defer = new $.Deferred();
			var items = $form.serialize();

			let $a_from=$form;
			let $select_form=$a_from.find(':input[name]').not(':checkbox');
			for(let i=0;i<$select_form.length;i++){
				let self=$($select_form.get(i));
				let value=self.val();
				let name=self.attr('name');
				var matches = name.match(/\[\w+\]/g);
				let test_string="media[test1][test2][test3]";
				var matches2 = test_string.match(/(\w+)(\[\w+\])*?/g);


				if(matches===null){
					continue;
				}
				/*
				let array_name=[];
				$.each(matches,function (index, item_name) {
					var matches1 = item_name.match(/(\w+)/g);
					array_name.push(matches1[0]);
				});
				 */
				//test[test1][test2][]
				name = name.replace(/]\[/gi, '.');
				name = name.replace(/\[/g, '.');
				name = name.replace(/]/g, '.');
				let lastTwoChar = name.substr(name.length - 2); // => "2"
				let lastChar = name.substr(name.length - 1); // => "1"
				if (lastTwoChar === "..") {
					name = name.substring(0, name.length - 2);
					//name=name+'[]';
				}else if(lastChar==="."){
					name = name.substring(0, name.length - 1);
				}

				self.attr('name', name);
			}
			$select_form.each(function (e) {

			});

			var obj = $select_form.serializeToJSON({
				// options here
			});


			var a =[];
			$.each(obj,function (key, item) {
				a.push({
					name:key,
					value:item
				});
			});
			//var a = $form.find(':input[name]').not(':checkbox').serializeArray();

			$form.find(':checkbox[name]').each(function() {
				if(this.hasAttribute('value')) {
					if(this.checked) a.push({
						name: this.name,
						value: this.value
					});
				}
				else a.push({
					name: this.name,
					value: this.checked
				});
			});
			defer.resolve(a);

			return defer.promise();
		}).then(function(a){
			var defer = new $.Deferred();

			var defers = [], readers = [];
			$form.find('input[type="file"][name]').each(function() {
				var input = $(this).get(0);
				console.log("name", $(this).attr('name'));
				for (var i = 0; i < input.files.length; i++) {
					defers.push(new $.Deferred());
					readers.push(new FileReader());

					var k = defers.length - 1;
					readers[k].onload = (function(file, defer, inputName) {
						return function(e) {							
							var dataURL = e.target.result;
							var pos = dataURL.indexOf(',') + 1;
							var fo = {
								name: file.name,
								type: file.type,
								size: file.size,
								data: pos ? dataURL.slice(pos) : null
							};							
							defer.resolve({
								name: inputName,
								value: fo
							});
						};
					})(input.files[i], defers[k], input.name);

					readers[k].onerror = (function(defer) {
						return function(e) {
							defer.reject(e.target.error);
						};
					})(defers[k]);

					readers[k].readAsDataURL(input.files[i]);
				}
			});
			$.when.apply($, defers).then(function() {
				if(arguments[0]) for(var i = 0; i < arguments.length; i++) a.push(arguments[i]);
				defer.resolve(a);
			}, function(e) {
				defer.reject(e);
			});

			return defer.promise();
		}).then(function(a) {
			var defer = new $.Deferred();

			var output = {};
			$.each(a, function() {
				var value_of_input = this.value === undefined ? '' : this.value;
				if (this.name.slice(-2) === '[]'){ // force array
					this.name = this.name.slice(0, -2);
					if (output[this.name] === undefined) output[this.name] = [];
				}
				if (output[this.name] !== undefined) {
					if (!output[this.name].push) {
						output[this.name] = [output[this.name]];
					}
					if(Array.isArray(value_of_input))
                        output[this.name]=value_of_input;
					else
						output[this.name].push(value_of_input);
				}
				else {
					output[this.name] = value_of_input;
				}
			});

			defer.resolve(output);

			return defer.promise();
		});
	};
})(jQuery);