// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.ui.form.MultiSelectDialog = Class.extend({
	init: function(opts) {
		/* Options: doctype, target, setters, get_query, action */
		$.extend(this, opts);

		var me = this;
		if(this.doctype!="[Select]") {
			frappe.model.with_doctype(this.doctype, function(r) {
				me.make();
			});
		} else {
			this.make();
		}
	},
	make: function() {
		let me = this;

		this.page_length = 20;

		let fields = [
			{
				fieldtype: "Data",
				label: __("Search Term"),
				fieldname: "search_term"
			},
			{
				fieldtype: "Column Break"
			}
		];
		let count = 0;
		if(!this.date_field) {
			this.date_field = "transaction_date";
		}
		Object.keys(this.setters).forEach(function(setter) {
			fields.push({
				fieldtype: me.target.fields_dict[setter].df.fieldtype,
				label: me.target.fields_dict[setter].df.label,
				fieldname: setter,
				options: me.target.fields_dict[setter].df.options,
				default: me.setters[setter]
			});
			if (count++ < Object.keys(me.setters).length) {
				fields.push({fieldtype: "Column Break"});
			}
		});

		fields = fields.concat([
			{
				"fieldname":"date_range",
				"label": __("Date Range"),
				"fieldtype": "DateRange",
			},
			{ fieldtype: "Section Break" },
			{ fieldtype: "HTML", fieldname: "results_area" },
			{ fieldtype: "Button", fieldname: "make_new", label: __("Make a new " + me.doctype) }
		]);

		let doctype_plural = !this.doctype.endsWith('y') ? this.doctype + 's'
			: this.doctype.slice(0, -1) + 'ies';

		this.dialog = new frappe.ui.Dialog({
			title: __("Select {0}", [(this.doctype=='[Select]') ? __("value") : __(doctype_plural)]),
			fields: fields,
			primary_action_label: __("Get Items"),
			primary_action: function() {
				me.action(me.get_checked_values(), me.args);
			}
		});

		this.$parent = $(this.dialog.body);
		this.$wrapper = this.dialog.fields_dict.results_area.$wrapper.append(`<div class="results"
			style="border: 1px solid #d1d8dd; border-radius: 3px; height: 300px; overflow: auto;"></div>`);
		this.$results = this.$wrapper.find('.results');
		this.$make_new_btn = this.dialog.fields_dict.make_new.$wrapper;

		this.$placeholder = $(`<div class="multiselect-empty-state">
					<span class="text-center" style="margin-top: -40px;">
						<i class="fa fa-2x fa-tags text-extra-muted"></i>
						<p class="text-extra-muted">No ${this.doctype} found</p>
						<button class="btn btn-default btn-xs text-muted" data-fieldtype="Button"
							data-fieldname="make_new" placeholder="" value="">Make a new ${this.doctype}</button>
					</span>
				</div>`);

		this.args = {};

		this.bind_events();
		this.get_results();
		this.dialog.show();
	},

	bind_events: function() {
		let me = this;
		this.$results.on('click', '.list-item-container', function (e) {
			if (!$(e.target).is(':checkbox') && !$(e.target).is('a')) {
				$(this).find(':checkbox').trigger('click');
			}
		});
		this.$results.on('click', '.list-item--head :checkbox', (e) => {
			this.$results.find('.list-item-container .list-row-check')
				.prop("checked", ($(e.target).is(':checked')));
		});

		this.$parent.find('.input-with-feedback').on('change', (e) => {
			this.get_results();
		});

		this.$parent.find('[data-fieldname="date_range"]').on('blur', (e) => {
			this.get_results();
		});

		this.$parent.find('[data-fieldname="search_term"]').on('input', (e) => {
			var $this = $(this);
			clearTimeout($this.data('timeout'));
			$this.data('timeout', setTimeout(function() {
				me.get_results();
			}, 300));
		});

		this.$parent.on('click', '.btn[data-fieldname="make_new"]', (e) => {
			frappe.route_options = {};
			Object.keys(this.setters).forEach(function(setter) {
				frappe.route_options[setter] = me.dialog.fields_dict[setter].get_value() || undefined;
			});
			frappe.new_doc(this.doctype, true);
		});
	},

	get_checked_values: function() {
		return this.$results.find('.list-item-container').map(function() {
			if ($(this).find('.list-row-check:checkbox:checked').length > 0 ) {
				return $(this).attr('data-item-name');
			}
		}).get();
	},

	make_list_row: function(result={}) {
		var me = this;
		// Make a head row by default (if result not passed)
		let head = Object.keys(result).length === 0;

		let contents = ``;
		let columns = (["name"].concat(Object.keys(this.setters))).concat("Date");
		columns.forEach(function(column) {
			contents += `<div class="list-item__content ellipsis">
				${
					head ? `<span class="ellipsis">${__(frappe.model.unscrub(column))}</span>`

					: (column !== "name" ? `<span class="ellipsis">${__(result[column])}</span>`
						: `<a href="${"#Form/"+ me.doctype + "/" + result[column]}" class="list-id ellipsis">
							${__(result[column])}</a>`)
				}
			</div>`;
		})

		let $row = $(`<div class="list-item">
			<div class="list-item__content" style="flex: 0 0 10px;">
				<input type="checkbox" class="list-row-check" ${result.checked ? 'checked' : ''}>
			</div>
			${contents}
		</div>`);

		head ? $row.addClass('list-item--head')
			: $row = $(`<div class="list-item-container" data-item-name="${result.name}"></div>`).append($row);
		return $row;
	},

	render_result_list: function(results, more = 0) {
		var me = this;
		this.$results.empty();
		if(results.length === 0) {
			this.$make_new_btn.addClass('hide');
			this.$results.append(me.$placeholder);
			return;
		}
		this.$make_new_btn.removeClass('hide');

		this.$results.append(this.make_list_row());
		results.forEach((result) => {
			me.$results.append(me.make_list_row(result));
		})
		if (more) {
			let message = __("Only {0} entries shown. Please filter for more specific results.", [this.page_length]);
			me.$results.append($(`<div class="text-muted small" style="text-align: center;
				margin: 10px;">${message}</div>`));
		}
	},

	get_results: function() {
		let me = this;

		let filters = this.get_query().filters;
		Object.keys(this.setters).forEach(function(setter) {
			filters[setter] = me.dialog.fields_dict[setter].get_value() || undefined;
			me.args[setter] = filters[setter];
		});

		let date_val = this.dialog.fields_dict["date_range"].get_value();
		if(date_val) {
			filters[this.date_field] = ['Between', me.dialog.fields_dict["date_range"].parse(date_val)];
		}

		let args = {
			doctype: me.doctype,
			txt: me.dialog.fields_dict["search_term"].get_value(),
			filters: filters,
			filter_fields: Object.keys(me.setters).concat([me.date_field]),
			page_length: this.page_length + 1,
			query: this.get_query().query,
			as_dict: 1
		}
		frappe.call({
			type: "GET",
			method:'frappe.desk.search.search_widget',
			no_spinner: true,
			args: args,
			callback: function(r) {
				let results = [], more = 0;
				if(r.values.length) {
					if(r.values.length > me.page_length){
						r.values.pop();
						more = 1;
					}
					r.values.forEach(function(result) {
						if(me.date_field in result) {
							result["Date"] = result[me.date_field]
						}
						result.checked = 0;
						result.parsed_date = Date.parse(result["Date"]);
						results.push(result);
					});
					results.map( (result) => {
						result["Date"] = frappe.format(result["Date"], {"fieldtype":"Date"});
					})

					results.sort((a, b) => {
						return a.parsed_date - b.parsed_date;
					});

					// Preselect oldest entry
					results[0].checked = 1
				}
				me.render_result_list(results, more);
			}
		});
	},

});