import * as DomEvent from './DomEvent';

/*
 * Extends the event handling code with double tap support for mobile browsers.
 *
 * Note: currently most browsers fire native dblclick, with only a few exceptions
 * (see https://github.com/Leaflet/Leaflet/issues/7012#issuecomment-595087386)
 */

function makeDblclick(event) {
	// in modern browsers `type` cannot be just overridden:
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only
	var newEvent = {},
	    prop, i;
	for (i in event) {
		prop = event[i];
		newEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
	}
	event = newEvent;
	newEvent.type = 'dblclick';
	newEvent.detail = 2;
	newEvent.isTrusted = false;
	newEvent._simulated = true; // for debug purposes
	return newEvent;
}

var delay = 200;
export function addDoubleTapListener(obj, handler) {
	// Most browsers handle double tap natively
	obj.addEventListener('dblclick', handler);

	// On some platforms the browser doesn't fire native dblclicks for touch events.
	// It seems that in all such cases `detail` property of `click` event is always `1`.
	// So here we rely on that fact to avoid excessive 'dblclick' simulation when not needed.
	var last = 0,
	    detail;
	function simDblclick(e) {
		if (e.detail !== 1) {
			detail = e.detail; // keep in sync to avoid false dblclick in some cases
			return;
		}

		if (e.pointerType === 'mouse' ||
			(e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)) {

			return;
		}

		// When clicking on an <input>, the browser generates a click on its
		// <label> (and vice versa) triggering two clicks in quick succession.
		// This ignores clicks on elements which are a label with a 'for'
		// attribute (or children of such a label), but not children of
		// a <input>.
		var path = DomEvent.getPropagationPath(e);
		if (path.some(function (el) {
			return el instanceof HTMLLabelElement && el.attributes.for;
		}) &&
			!path.some(function (el) {
				return (
					el instanceof HTMLInputElement ||
					el instanceof HTMLSelectElement
				);
			})
		) {
			return;
		}

		var now = Date.now();
		if (now - last <= delay) {
			detail++;
			if (detail === 2) {
				handler(makeDblclick(e));
			}
		} else {
			detail = 1;
		}
		last = now;
	}

	obj.addEventListener('click', simDblclick);

	return {
		dblclick: handler,
		simDblclick: simDblclick
	};
}

export function removeDoubleTapListener(obj, handlers) {
	obj.removeEventListener('dblclick', handlers.dblclick);
	obj.removeEventListener('click', handlers.simDblclick);
}
