import $ from 'jquery';

const $wnd = $( window );

/**
 * Check if lines cross
 *
 * @param {Object} a - first point of the first line
 * @param {Object} b - second point of the first line
 * @param {Object} c - first point of the second line
 * @param {Object} d - second point of the second line
 *
 * @return {boolean} cross lines
 */
function isCrossLine( a, b, c, d ) {
	// Working code #1:
	//
	// var common = (b.x - a.x)*(d.y - c.y) - (b.y - a.y)*(d.x - c.x);
	// if (common === 0) {
	//     return false;
	// }
	//
	// var rH = (a.y - c.y)*(d.x - c.x) - (a.x - c.x)*(d.y - c.y);
	// var sH = (a.y - c.y)*(b.x - a.x) - (a.x - c.x)*(b.y - a.y);
	//
	// var r = rH / common;
	// var s = sH / common;
	//
	// return r >= 0 && r <= 1 && s >= 0 && s <= 1;

	// Working code #2:
	const v1 = ( d.x - c.x ) * ( a.y - c.y ) - ( d.y - c.y ) * ( a.x - c.x );
	const v2 = ( d.x - c.x ) * ( b.y - c.y ) - ( d.y - c.y ) * ( b.x - c.x );
	const v3 = ( b.x - a.x ) * ( c.y - a.y ) - ( b.y - a.y ) * ( c.x - a.x );
	const v4 = ( b.x - a.x ) * ( d.y - a.y ) - ( b.y - a.y ) * ( d.x - a.x );
	return v1 * v2 <= 0 && v3 * v4 <= 0;
}

// Init Events.
$( document ).on( 'initEvents.vpf', ( event, self ) => {
	if ( event.namespace !== 'vpf' || self.options.itemsStyle !== 'fly' ) {
		return;
	}

	const evp = `.vpf-uid-${ self.uid }`;

	// determine cursor position
	let lastCursorPos = {};
	$wnd.on( `mousemove${ evp }`, ( e ) => {
		lastCursorPos = {
			x: e.clientX,
			y: e.clientY,
		};
	} );

	self.$item.on(
		`mouseenter${ evp } mouseleave${ evp }`,
		'.vp-portfolio__item',
		function ( e ) {
			const $this = $( this );
			const itemRect = $this[ 0 ].getBoundingClientRect();
			const $overlay = $this.find( '.vp-portfolio__item-overlay' );
			const enter = e.type === 'mouseenter';
			let endX = '0%';
			let endY = '0%';
			const curCursorPos = {
				x: e.clientX,
				y: e.clientY,
			};

			// find the corner that placed on cursor path.
			let isUp = isCrossLine(
				{ x: itemRect.left, y: itemRect.top },
				{ x: itemRect.left + itemRect.width, y: itemRect.top },
				curCursorPos,
				lastCursorPos
			);
			let isDown = isCrossLine(
				{ x: itemRect.left, y: itemRect.top + itemRect.height },
				{
					x: itemRect.left + itemRect.width,
					y: itemRect.top + itemRect.height,
				},
				curCursorPos,
				lastCursorPos
			);
			let isLeft = isCrossLine(
				{ x: itemRect.left, y: itemRect.top },
				{ x: itemRect.left, y: itemRect.top + itemRect.height },
				curCursorPos,
				lastCursorPos
			);
			let isRight = isCrossLine(
				{ x: itemRect.left + itemRect.width, y: itemRect.top },
				{
					x: itemRect.left + itemRect.width,
					y: itemRect.top + itemRect.height,
				},
				curCursorPos,
				lastCursorPos
			);

			// Sometimes isCrossLine returned false, so we need to check direction manually (less accurate, but it is not a big problem).
			if ( ! isUp && ! isDown && ! isLeft && ! isRight ) {
				const x =
					( itemRect.width / 2 - curCursorPos.x + itemRect.left ) /
					( itemRect.width / 2 );
				const y =
					( itemRect.height / 2 - curCursorPos.y + itemRect.top ) /
					( itemRect.height / 2 );
				if ( Math.abs( x ) > Math.abs( y ) ) {
					if ( x > 0 ) {
						isLeft = true;
					} else {
						isRight = true;
					}
				} else if ( y > 0 ) {
					isUp = true;
				} else {
					isDown = true;
				}
			}

			if ( isUp ) {
				endY = '-100.1%';
			} else if ( isDown ) {
				endY = '100.1%';
			} else if ( isLeft ) {
				endX = '-100.1%';
			} else if ( isRight ) {
				endX = '100.1%';
			}

			if ( enter ) {
				$overlay.css( {
					transition: 'none',
					transform: `translateX(${ endX }) translateY(${ endY }) translateZ(0)`,
				} );
				// Trigger a reflow, flushing the CSS changes. This need to fix some glitches in Safari and Firefox.
				// Info here - https://stackoverflow.com/questions/11131875/what-is-the-cleanest-way-to-disable-css-transition-effects-temporarily
				// eslint-disable-next-line no-unused-expressions
				$overlay[ 0 ].offsetHeight;
			}

			$overlay.css( {
				transition: '.2s transform ease-in-out',
				transform: `translateX(${ enter ? '0%' : endX }) translateY(${
					enter ? '0%' : endY
				}) translateZ(0)`,
			} );
		}
	);
} );

// Destroy Events.
$( document ).on( 'destroyEvents.vpf', ( event, self ) => {
	if ( event.namespace !== 'vpf' || self.options.itemsStyle !== 'fly' ) {
		return;
	}

	const evp = `.vpf-uid-${ self.uid }`;

	$wnd.off( `mousemove${ evp }` );
	self.$item.off( `mouseenter${ evp } mouseleave${ evp }` );
} );
