/**
 * EGroupware eTemplate2 - Functions which allow resizing of table headers
 *
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
 * @package etemplate
 * @subpackage dataview
 * @link https://www.egroupware.org
 * @author Andreas Stöckel
 * @copyright EGroupware GmbH 2011-2021
 */

import {egw} from "../jsapi/egw_global";

/**
 * This set of functions is currently only supporting resizing in ew-direction
 */

export class et2_dataview_view_resizable
{

	// Define some constants
	public static readonly RESIZE_BORDER = 12;
	public static readonly RESIZE_MIN_WIDTH = 25;
	public static readonly RESIZE_ADD = 2; // Used to ensure mouse is under the resize element after resizing has finished


	public static helper : JQuery = null;
	public static overlay : JQuery = null;
	public static didResize = false;
	public static resizeWidth = 0;

	// In resize region returns whether the mouse is currently in the
	// "resizeRegion"
	public static  inResizeRegion(_x, _elem)
	{
		var ol = _x - _elem.offset().left;
		return (ol > (_elem.outerWidth(true) - et2_dataview_view_resizable.RESIZE_BORDER));
	}

	public static startResize(_outerElem, _elem, _callback, _column)
	{
		if (this.overlay == null || this.helper == null)
		{
			// Prevent text selection
			// FireFox handles highlight prevention (text selection) different than other browsers
			if (typeof _elem[0].style.MozUserSelect !="undefined")
			{
				_elem[0].style.MozUserSelect = "none";
			}
			else
			{
				_elem[0].onselectstart = function() {
					return false;
				};
			}

			// Indicate resizing is in progress
			jQuery(_outerElem).addClass('egwResizing');

			// Reset the "didResize" flag
			this.didResize = false;

			// Create the resize helper
			var left = _elem.offset().left;
			this.helper = jQuery(document.createElement("div"))
				.addClass("egwResizeHelper")
				.appendTo("body")
				.css("top", _elem.offset().top + "px")
				.css("left", left + "px")
				.css("height", _outerElem.outerHeight(true) + "px");

			// Create the overlay which will be catching the mouse movements
			this.overlay = jQuery(document.createElement("div"))
				.addClass("egwResizeOverlay")

				.bind("mousemove", function(e) {
					this.didResize = true;
					this.resizeWidth = Math.max(e.pageX - left + et2_dataview_view_resizable.RESIZE_ADD,
						_column && _column.minWidth ? _column.minWidth : et2_dataview_view_resizable.RESIZE_MIN_WIDTH
					);
					this.helper.css("width", this.resizeWidth + "px");
				}.bind(this))

				.bind("mouseup", function() {
					this.stopResize(_outerElem);

					// Reset text selection
					_elem[0].onselectstart = null;

					// Call the callback if the user actually performed a resize
					if (this.didResize)
					{
						_callback(this.resizeWidth);
					}
				}.bind(this))
				.appendTo("body");
		}
	}

	public static stopResize(_outerElem)
	{

		jQuery(_outerElem).removeClass('egwResizing');
		if (this.helper != null)
		{
			this.helper.remove();
			this.helper = null;
		}

		if (this.overlay != null)
		{
			this.overlay.remove();
			this.overlay = null;
		}
	}

	public static makeResizeable = function(_elem, _callback, _context)
	{
		// Get the table surrounding the given element - this element is used to
		// align the helper properly
		var outerTable = _elem.closest("table");

		// Bind the "mousemove" event in the "resize" namespace
		_elem.bind("mousemove.resize", function(e) {
			var stopResize = false;
			// Stop switch to resize cursor if the mouse position
			// is more intended for scrollbar not the resize edge
			// 8pixel is an arbitary number for scrolbar area
			if (e.target.clientHeight < e.target.scrollHeight && e.target.offsetWidth - e.offsetX <= 8)
			{
				stopResize = true;
			}
			_elem.css("cursor", et2_dataview_view_resizable.inResizeRegion(e.pageX, _elem) && !stopResize? "ew-resize" : "auto");
		});

		// Bind the "mousedown" event in the "resize" namespace
		_elem.bind("mousedown.resize", function(e) {
			var stopResize = false;
			// Stop resize if the mouse position is more intended
			// for scrollbar not the resize edge
			// 8pixel is an arbitary number for scrolbar area
			if (e.target.clientHeight < e.target.scrollHeight && e.target.offsetWidth - e.offsetX <= 8)
			{
				stopResize = true;
			}
			// Do not triger startResize if clicked element is select-tag, as it may causes conflict in some browsers
			if (et2_dataview_view_resizable.inResizeRegion(e.pageX, _elem) && e.target.tagName != 'SELECT' && !stopResize)
			{
				// Start the resizing
				et2_dataview_view_resizable.startResize(outerTable, _elem, function(_w) {
					_callback.call(_context, _w);
				}, _context);
			}

		});

		// Bind double click for auto-size
		_elem.dblclick(function(e) {
			// Just show message for relative width columns
			if(_context && _context.relativeWidth)
			{
				return egw.message(egw.lang('You tried to automatically size a flex column, which always takes the rest of the space','info'));
			}
			// Find column class - it's usually the first one
			var col_class = '';
			for(var i = 0; i < this.classList.length; i++)
			{
				if(this.classList[i].indexOf('gridCont') === 0)
				{
					col_class = this.classList[i];
					break;
				}
			}

			// Find widest part, including header
			var column = jQuery(this);
			column.children().css('width','auto');
			var max_width = column.children().children().innerWidth();
			var padding = column.outerWidth(true) - max_width;
			
			var resize = jQuery(this).closest('.egwGridView_outer')
				.find('tbody td.'+col_class+'> div:first-child')
				.add(column.children())
			// Set column width to auto to allow space for everything to flow
				.css('width','auto');
			resize.children()
				.css({'white-space':'nowrap'})
				.each(function()
					{
						var col = jQuery(this);
						// Find visible (text) children and force them to not wrap
						var children = col.find('span:visible, time:visible, label:visible')
							.css({'white-space':'nowrap'});
						this.offsetWidth;
						children.each(function()
						{
							var child = jQuery(this);
							this.offsetWidth;
							if(child.outerWidth() > max_width)
							{
								max_width = child.outerWidth();
							}
							window.getComputedStyle(this).width;
						});
						this.offsetWidth;
						if(col.innerWidth() > max_width)
						{
							max_width = col.innerWidth();
						}

						// Reset children
						children.css('white-space','');
						children.css('display','');
					}
				)
				.css({'white-space':''});
		
			// Reset column
			column.children().css('width','');
			resize.css('width','');
			_callback.call(_context, max_width+padding);
		});
	};

	public static et2_dataview_resetResizeable = function(_elem)
	{
		// Remove all events in the ".resize" namespace from the element
		_elem.unbind(".resize");
	}
}