/**
 * ALB Shortcode Image Difference frontend and preview iframe
 *
 * @added by guenter
 * @since 5.5
 */
"use strict";

//	global namespace
var avia_js_shortcodes = avia_js_shortcodes || {};
var aviaJS = aviaJS || {};

(function()
{
	if( ! avia_js_shortcodes.aviaImageDiff )
	{
		class scAviaImageDiff
		{
			container = null;		//	container element
			id = '';
			divider = 'vertical';			//	'vertical' | 'horizontal'
			handle = null;
			settings = {};
			wrapperDiv = []
			btnOverlay = [];
			btnBefore = [];
			btnAfter = [];
			imgBefore = [];
			imgAfter = [];
			imgDimension = {};
			mouseCapture = false;
			touchCapture = false;
			touchMoved = false;
			downScreenX = 0;
			downScreenY = 0;
			downClientX = 0;
			downClientY = 0;
			downHandlePos = 0;
			preview = false;

			constructor( container )
			{
				this.container = container;
				this.container.scAviaImageDiff = this;
				this.id = container.getAttribute('id');

				this.handle = container.getElementsByClassName( 'av-image-diff-handle' );
				if( ! this.handle.length )
				{
					return;
				}

				this.handle = this.handle[0];

				this.init();
			}

			init()
			{
				this.settings = JSON.parse( this.container.dataset.image_diff );
				this.wrapperDiv = this.container.getElementsByClassName( 'av-image-diff-wrapper' );
				this.btnOverlay = this.container.getElementsByClassName( 'av-image-diff-overlay' );
				this.btnBefore = this.btnOverlay[0].getElementsByClassName( 'label-before' );
				this.btnAfter = this.btnOverlay[0].getElementsByClassName( 'label-after' );
				this.imgBefore = this.container.getElementsByClassName( 'av-img-before' );
				this.imgAfter = this.container.getElementsByClassName( 'av-img-after' );

				if( ! this.imgBefore.length || ! this.imgAfter.length )
				{
					this.hideHandlerDOM();
					return;
				}

				if( this.container.classList.contains( 'av-handle-horizontal' ) )
				{
					this.divider = 'horizontal';
				}

				this.preview = document.getElementById( 'av-admin-preview' ) != null;

				this.bindEvents();
				this.initialPositionHandler();
			}

			hideHandlerDOM()
			{
				this.handle.style.display = 'none';

				if( this.btnOverlay.length )
				{
					this.btnOverlay[0].style.display = 'none';
				}
			}

			initialPositionHandler()
			{
				let start = ( 'undefined' == typeof this.settings.drag_start ) ? 50 : parseInt( this.settings.drag_start );
				if( isNaN( start ) )
				{
					start = 50;
				}

				let offset = 0;

				this.imgDimension = this.imgBefore[0].getBoundingClientRect();

				if( this.divider == 'horizontal' )
				{
					offset = this.imgDimension.height * ( start / 100.0 );
				}
				else
				{
					offset = this.imgDimension.width  * ( start / 100.0 );
				}

				this.container.classList.add( 'av-initialise' );

				this.adjustDividerFrame( offset );

				let obj = this;

				setTimeout( function()
				{
					obj.container.classList.remove( 'av-initialise' );
				}, 700 );
			}

			adjustDividerFrame( offset )
			{
				const overhead = 5;

				this.container.classList.remove( 'av-handler-at-before', 'av-handler-at-after');

				offset = Math.round( offset );

				if( offset <= 0 )
				{
					offset = 0;
					this.container.classList.add( 'av-handler-at-before' );
				}

				if( this.divider == 'horizontal' )
				{
					if( offset >= ( this.imgDimension.height + overhead ) )
					{
						offset = Math.round( this.imgDimension.height + overhead );
						this.container.classList.add( 'av-handler-at-after' );
					}

					let bottom = this.imgDimension.height - offset;

					this.handle.style.top = offset + 'px';
					this.imgBefore[0].style['clip-path'] = 'inset( 0 0 ' + bottom + 'px 0 )';
					this.imgAfter[0].style['clip-path'] = 'inset( ' + offset + 'px 0 0 0 )';
				}
				else
				{
					if( offset >= ( this.imgDimension.width + overhead ) )
					{
						offset = Math.round( this.imgDimension.width + overhead );
						this.container.classList.add( 'av-handler-at-after' );
					}

					let right = this.imgDimension.width - offset;

					this.handle.style.left = offset + 'px';
					this.imgBefore[0].style['clip-path'] = 'inset( 0 ' + right + 'px 0 0 )';
					this.imgAfter[0].style['clip-path'] = 'inset( 0 0 0 ' + offset + 'px )';
				}
			}

			bindEvents()
			{
				//	jQuery event hack -> see lottie_animation.js
				this.container.onavia_start_animation = ( e ) =>
				{
					const opt = {
								'bubbles':		true,
								'cancelable':	true
							};

					const event = new CustomEvent( 'avia_start_animation', opt );
					this.container.dispatchEvent( event );
				};

				this.container.addEventListener( 'avia_start_animation', this.onAviaStartAnimation.bind( this ) );


				this.handle.addEventListener( 'click', this.onHandleClick.bind( this ) );
				this.handle.addEventListener( 'mousedown', this.onMouseDown.bind( this ) );

				if( this.wrapperDiv.length > 0 )
				{
					this.wrapperDiv[0].addEventListener( 'click', this.onClickWrapper.bind( this ) );
					this.wrapperDiv[0].addEventListener( 'touchstart', this.onTouchStart.bind( this ) );
				}

				if( this.btnBefore.length > 0 )
				{
					this.btnBefore[0].addEventListener( 'click', this.onClickBtnBefore.bind( this ) );
				}

				if( this.btnAfter.length > 0 )
				{
					this.btnAfter[0].addEventListener( 'click', this.onClickBtnAfter.bind( this ) );
				}

				window.addEventListener( 'mousemove', this.onMouseMove.bind( this ) );
				window.addEventListener( 'mouseup', this.onMouseUp.bind( this ) );
				window.addEventListener( 'touchmove', this.onTouchMove.bind( this ) );
				window.addEventListener( 'touchend', this.onTouchEnd.bind( this ) );
				window.addEventListener( 'resize', aviaJS.aviaJSHelpers.debounce( this.onResize.bind( this ), 200 ) );

				if( this.preview )
				{
					this.container.addEventListener( 'animationend', this.onAnimationEnd.bind( this ) );
				}
			}

			onAviaStartAnimation( event )
			{
				if( this.container.classList.contains( 'avia_animation_finished' ) )
				{
					return;
				}

				if( this.preview )
				{
					//	modal preview does not have waypoint script - simulate it
					this.container.classList.add( 'avia_start_animation', 'avia_animation_finished' );
				}

				if( 'undefined' != typeof event )
				{
					this.container.classList.add( 'avia_animation_finished', 'avia_start_delayed_animation' );
				}
			}

			onAnimationEnd( event )
			{
				if( ! this.preview )
				{
					return;
				}

				this.initialPositionHandler();
			}

			onMouseDown( event )
			{
				if( this.touchCapture )
				{
					return;
				}

				event.preventDefault();
				event.stopPropagation();

				this.mouseCapture = true;
				this.container.classList.add( 'av-active-drag' );

				this.downScreenX = event.screenX;
				this.downScreenY = event.screenY;

				if( this.divider == 'horizontal' )
				{
					this.downHandlePos = this.handle.style.top;
				}
				else
				{
					this.downHandlePos = this.handle.style.left;
				}

				this.downHandlePos = parseInt( this.downHandlePos.replace( 'px', '' ) );
			}

			onMouseMove( event )
			{
				if( ! this.mouseCapture )
				{
					return;
				}

				event.preventDefault();
				event.stopPropagation();

				let newPos = 0,
					diff = 0;

				if( this.divider == 'horizontal' )
				{
					diff = event.screenY - this.downScreenY;
				}
				else
				{
					diff = event.screenX - this.downScreenX;
				}

				if( Math.abs( diff ) < 5 )
				{
					return;
				}

				newPos = this.downHandlePos + diff;

				this.adjustDividerFrame( newPos );
			}

			onMouseUp( event )
			{
				if( ! this.mouseCapture )
				{
					return;
				}

				event.preventDefault();
				event.stopPropagation();

				this.mouseCapture = false;
				this.container.classList.remove( 'av-active-drag' );
			}

			onTouchStart( event )
			{
				if( this.mouseCapture )
				{
					return;
				}

				if( ! event.touches.length )
				{
					return;
				}

				event.preventDefault();
				event.stopPropagation();

				if( event.explicitOriginalTarget )
				{
					//	pass click event to button when visible !!!
					if( event.explicitOriginalTarget.classList.contains( 'av-img-diff-label' ) )
					{
						let opacity = window.getComputedStyle( event.explicitOriginalTarget ).getPropertyValue( 'opacity' );

						if( opacity > 0 )
						{
							event.explicitOriginalTarget.dispatchEvent( new MouseEvent( 'click' ) );
							return;
						}
					}
				}

				this.touchCapture = true;
				this.container.classList.add( 'av-active-drag' );

				this.downScreenX = event.touches[0].screenX;
				this.downScreenY = event.touches[0].screenY;
				this.downClientX = event.touches[0].clientX;
				this.downClientY = event.touches[0].clientY;

				if( this.divider == 'horizontal' )
				{
					this.downHandlePos = this.handle.style.top;
				}
				else
				{
					this.downHandlePos = this.handle.style.left;
				}

				this.downHandlePos = parseInt( this.downHandlePos.replace( 'px', '' ) );
			}

			onTouchMove( event )
			{
				if( ! this.touchCapture )
				{
					return;
				}

				event.preventDefault();
				event.stopPropagation();

				let newPos = 0,
					diff = 0;

				if( this.divider == 'horizontal' )
				{
					diff = event.touches[0].screenY - this.downScreenY;
				}
				else
				{
					diff = event.touches[0].screenX - this.downScreenX;
				}

				if( Math.abs( diff ) < 5 )
				{
					return;
				}

				newPos = this.downHandlePos + diff;

				this.adjustDividerFrame( newPos );
				this.touchMoved = true;
			}

			onTouchEnd( event )
			{
				if( ! this.touchCapture )
				{
					return;
				}

				if( ! this.touchMoved )
				{
					let newPos = 0,
						maxCheck = 0,
						rect = this.wrapperDiv[0].getBoundingClientRect();

					if( this.divider == 'horizontal' )
					{
						newPos = this.downClientY - rect.top;
						maxCheck = rect.height;
					}
					else
					{
						newPos = this.downClientX - rect.left;
						maxCheck = rect.width;
					}

					if( newPos < 0 )
					{
						newPos = 0;
					}
					else if( newPos > maxCheck )
					{
						newPos = maxCheck;
					}

					this.adjustDividerFrame( newPos );
				}

				event.preventDefault();
				event.stopPropagation();

				this.touchCapture = false;
				this.touchMoved = false;
				this.container.classList.remove( 'av-active-drag' );
			}

			onResize( event )
			{
				let lastPos = 0,
					lastDim = 0;

				if( this.divider == 'horizontal' )
				{
					lastPos = this.handle.style.top;
					lastDim = this.imgDimension.height;
				}
				else
				{
					lastPos = this.handle.style.left;
					lastDim = this.imgDimension.width;
				}

				lastPos = parseInt( lastPos.replace( 'px', '' ) );

				if( lastPos < 0 )
				{
					lastDim = 0;
				}
				else if( lastDim != 0 )
				{
					lastDim = Math.round( ( lastPos / lastDim ) * 100.0 );
				}

				if( lastDim > 100 )
				{
					lastDim = 100;
				}

				this.settings.drag_start = lastDim;

				this.imgBefore[0].style['clip-path'] = 'inset( 0 0 0 0 )';
				this.imgAfter[0].style['clip-path'] = 'inset( 0 0 0 0 )';

				this.initialPositionHandler();
			}

			onHandleClick( event )
			{
				//	needed to prevent jumping around after mouse move events
				event.preventDefault();
				event.stopPropagation();
			}

			onClickBtnBefore( event )
			{
				event.preventDefault();
				event.stopPropagation();

				this.adjustDividerFrame( 0 );
			}

			onClickBtnAfter( event )
			{
				event.preventDefault();
				event.stopPropagation();

				let newPos = 0;

				if( this.divider == 'horizontal' )
				{
					newPos = this.imgDimension.height;
				}
				else
				{
					newPos = this.imgDimension.width;
				}

				this.adjustDividerFrame( newPos + 15 );
			}

			onClickWrapper( event )
			{
				event.preventDefault();
				event.stopPropagation();

				let newPos = 0;

				if( this.divider == 'horizontal' )
				{
					newPos = event.layerY;
				}
				else
				{
					newPos = event.layerX;
				}

				this.adjustDividerFrame( newPos );
			}

		}

		//	class factory
		avia_js_shortcodes.aviaImageDiff = function( container )
		{
			return new scAviaImageDiff( container );
		};

		aviaJS.aviaPlugins.register( avia_js_shortcodes.aviaImageDiff, '.avia-image-diff-container' );
	}

})();