/*! © SpryMedia Ltd - datatables.net/license */

/**
 * @summary     Download Button
 * @author      SpryMedia Ltd (www.datatables.net)
 * @copyright   Copyright 2018 SpryMedia Ltd.
 *
 * License      MIT - http://datatables.net/license/mit
 *
 * A button that can be used to trigger a server-side action, typically a
 * download of a file generated by the server. If server-side processing
 * is enabled in the host table it will automatically add the last parameters
 * used for a table draw allowing the script to output a file with the same
 * order / search applied as the main table.
 *
 * This is particularly useful when using server-side processing and wishing
 * to allow user export of the data in a table. The default Buttons package
 * will only export the data available on the client-side, while this button
 * can be used to let the server generate the required file and then download
 * it to the client-side.
 *
 * @example
 *   // Download button
 * 	var table = $('#example').DataTable({
 * 		dom: 'Bfrtip',
 * 		buttons: [
 * 			{
 * 				extend: 'download',
 * 				url: '/api/download'
 * 			}
 * 		]
 * 	});
 */

import DataTable from 'datatables.net';

declare module 'datatables.net' {
	interface Api<T> {
		/** Average the values in a data set. */
		average(): Number;
	}
}

function flattenJson(data, name?, flattened?) {
	if (!flattened) {
		flattened = {};
	}

	if (!name) {
		name = '';
	}

	if ($.isPlainObject(data) || Array.isArray(data)) {
		$.each(data, function (idx, val) {
			if (name === '') {
				flattenJson(val, idx, flattened);
			}
			else {
				flattenJson(val, name + '[' + idx.toString() + ']', flattened);
			}
		});
	}
	else {
		flattened[name] = data;
	}

	return flattened;
}

DataTable.ext.buttons.download = {
	text: 'Download',
	action: function (e, dt, node, config) {
		// Gather information to be submitted
		var data = {};

		if (dt.page.info().serverSide) {
			$.extend(data, dt.ajax.params());
		}

		if (typeof config.data === 'function') {
			config.data(data);
		}
		else if (typeof config.data === 'object') {
			$.extend(data, config.data);
		}

		// Convert data to a flat structure for submission
		var flattened = flattenJson(data);

		// Create an iframe
		var iframe = $('<iframe/>')
			.css({
				border: 'none',
				height: 0,
				width: 0,
			})
			.appendTo(document.body);

		var contentDoc = (iframe[0] as any).contentWindow.document;
		contentDoc.open();
		contentDoc.close();

		var form = $('<form/>', contentDoc)
			.attr('method', config.type)
			.attr('action', config.url)
			.appendTo(contentDoc.body);

		$.each(flattened, function (name, val) {
			$('<input/>', contentDoc)
				.attr('type', 'text')
				.attr('name', name.toString())
				.attr('autocomplete', 'no')
				.val(val)
				.appendTo(form);
		});

		form.submit();
	},
	url: '',
	type: 'POST',
	data: {},
};
