main/classes/StickyVideo.js

/* global gnca_settings */
/* global gn_analytics */

import InView from '../../utils/classes/InView';
import InBounds from './InBounds';
import Messenger from '../Messenger';
import customEvent from '../../utils/customEvent';
import updateIconPath from '../../utils/updateIconPath';

/**
 * Sticky Video functionality.
 * Handles multiple potential sticky videos on the same page.
 * Only one video may be sticky at a time.
 * This is a class because each sticky video needs to be initialized independently.
 *
 * @class StickyVideo
 * @prop {string} stickyAttribute - CSS selector for videos that should be made sticky
 * @prop {string} wrapperTemplate - Sticky video markup to wrap around player embeds
 * @prop {object} stickySelectors - list of CSS classes which apply to sticky video elements
 * @prop {string} pageContainerSelector - selector for the sticky video parent container
 * @prop {object} pageContainerListener - In View listener of pageContainer element
 * @prop {boolean} activeIFramePaused - T/F if the active sticky player is paused while unstuck
 * @prop {string} activeIFrameId - ID of the active sticky player if one exists
 * @prop {object} videoObserver - InView instance for observing video object
 * @prop {object} containerObserver - InBounds instance for observing container
 * @prop {float} intersectionRatio - Proportion of player visible below which we switch to sticky
 */
class StickyVideo {
	static stickyAttribute = 'data-displayinline-player-id';

	static wrapperTemplate = `
		<div class="c-video__stickyGrid c-stickyVideo__grid">
			<div class="c-video__stickySpacer c-stickyVideo__spacer"></div>
			<div class="c-stickyVideo__inner">
				<div class="c-stickyVideo__innerContainer">
					<div class="c-stickyVideo__info">
						<span class="c-stickyVideo__title">
							<div class="c-stickyVideo__text">&nbsp;</div>
						</span>
						<div class="c-stickyVideo__buttons">
							<button class="c-stickyVideo__close">
								<span class="sr-only">close video</span>
								<svg class="c-stickyVideo__icon c-icon">
									<use xlink:href="#close" />
								</svg>
							</button>
							<button class="c-stickyVideo__mute" data-video-action="mute">
								<span class="sr-only">mute video</span>
								<svg class="c-stickyVideo__icon c-icon c-icon--black">
									<use xlink:href="#volume-mute" />
								</svg>
							</button>
							<button class="c-stickyVideo__unmute" data-video-action="unmute">
								<span class="sr-only">unmute video</span>
								<svg class="c-stickyVideo__icon c-icon c-icon--black">
									<use xlink:href="#volume-unmute" />
								</svg>
							</button>
						</div>
					</div>
				</div>
			</div>
			<div class="c-stickyVideo__loader c-loader"></div>
		</div>
	`;

	static stickySelectors = {
		element: 'c-stickyVideo',
		container: 'c-video__sticky',
		inner: 'c-stickyVideo__inner',
		innerContainer: 'c-stickyVideo__innerContainer',
		title: 'c-stickyVideo__text',
		close: 'c-stickyVideo__close',
		mute: 'c-stickyVideo__mute',
		unmute: 'c-stickyVideo__unmute',
		embed: 'c-stickyVideo__embed',
		icon: 'c-stickyVideo__icon use',
		states: {
			loading: 'c-stickyVideo--loading',
			stuck: 'c-stickyVideo--stuck',
			detatched: 'c-stickyVideo--detached',
			anchored: 'c-stickyVideo--anchored',
			container: 'c-video--stuck',
			muted: 'c-stickyVideo--muted',
			cascadedContainer: 'is-static',
		},
	}

	static pageContainerSelector = '.l-main';

	static pageContainerListener = null;

	static videoListener = null;

	static activeIFramePaused = false;

	static activeIFrameId = null;

	static videoObserver = null;

	static containerObserver = null;

	static intersectionRatio = 0.3;

	static messageType = 'gnca_video';

	static messengerRegistered = false;

	static disabled = false;

	/**
	 * ID of video iframe
	 *
	 * @type {string}
	 * @member iframeId
	 */
	iframeId = null;

	/**
	 * Video player element
	 *
	 * @type {Element}
	 * @member $video
	 */
	$video = null;

	videoInstance = null;

	/**
	 * @constructs
	 */
	constructor( $video, videoInstance ) {
		this.$video = $video;
		this.iframeId = $video.getAttribute( 'id' );
		this.videoInstance = videoInstance;
	}

	/**
	 * Initializes sticky video, adding sticky markup and event listeners.
	 * Closes any open sticky videos in the process.
	 *
	 * @method init
	 * @returns {Element} Video player with sticky video markup added
	 */
	init() {
		// check if sticky video is enabled and ID is set
		if ( ! StickyVideo.stickyEnabled() || ! this.iframeId ) {
			return this.$video;
		}

		// remove any current sticky videos
		StickyVideo.detachCurrentVideo();

		// add sticky markup
		const $wrapper = this.addStickyMarkup();

		// Register receiver
		if ( ! StickyVideo.messengerRegistered ) {
			Messenger.registerReceiver( StickyVideo.messageType, StickyVideo );
			StickyVideo.messengerRegistered = true;
		}

		return $wrapper;
	}

	/**
	 * Wrap $video tag in sticky video markup.
	 *
	 * @method addStickyMarkup
	 * @returns {Element} Video player with sticky video markup added
	 */
	addStickyMarkup() {
		const $wrapper = document.createElement( 'div' );
		$wrapper.innerHTML = StickyVideo.wrapperTemplate;

		// update svg sprite path for close button
		const $icons = $wrapper.querySelectorAll( `.${StickyVideo.stickySelectors.icon}` );
		[].forEach.call( $icons, ( $icon ) => {
			updateIconPath( $icon );
		});

		// add video element
		$wrapper.setAttribute( 'id', `${this.iframeId}__sticky` );
		$wrapper.classList.add( StickyVideo.stickySelectors.element );
		$wrapper.classList.add( StickyVideo.stickySelectors.container );
		$wrapper.classList.add( StickyVideo.stickySelectors.states.loading );

		$wrapper.querySelector( `.${StickyVideo.stickySelectors.innerContainer}` ).appendChild( this.$video );
		$wrapper.querySelector( `.${StickyVideo.stickySelectors.close}` ).addEventListener( 'click', StickyVideo.close );
		$wrapper.querySelector( `.${StickyVideo.stickySelectors.mute}` ).addEventListener( 'click', StickyVideo.sendVideoAction );
		$wrapper.querySelector( `.${StickyVideo.stickySelectors.unmute}` ).addEventListener( 'click', StickyVideo.sendVideoAction );

		this.$video.classList.add( StickyVideo.stickySelectors.embed );

		return $wrapper;
	}

	/**
	 * Updates video status and potentially title based on info passed in event.
	 *
	 * @method receiveMessage
	 * @param {Object} event - Event object received from child iframe post message
	 */
	static receiveMessage( data ) {
		StickyVideo.updateStatus( data );

		if ( data.title ) {
			StickyVideo.updateTitle( data.title,
				data.show,
				data.isAd,
				data.iframeId );
		}
	}

	/**
	 * Updates sticky behavior based on new video status.
	 *
	 * @method updateStatus
	 * @param {string} status - new video state
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static updateStatus( data ) {
		const { status } = data;
		const { iframeId } = data;

		switch ( status ) {
		case 'playing':
			StickyVideo.activateVideo( iframeId );
			StickyVideo.updateVolume( data );
			break;
		case 'paused':
			StickyVideo.pauseVideo( iframeId );
			break;
		case 'loaded':
			StickyVideo.removeLoadIndicator( iframeId );
			break;
		case 'mute':
			StickyVideo.updateVolume( data );
			break;
		case 'upNext':
			if ( data.item ) {
				StickyVideo.updateTitle( data.item.title, 'Up Next', false, iframeId );
			}
			break;
		case 'pipEnter':
			// Player entered picture in picture mode, disable sticky video.
			StickyVideo.disable();
			break;
		case 'pipLeave':
			// Player left picture in picture mode,
			// bring video in view and re-enable sticky video.
			StickyVideo.focusVideo();
			StickyVideo.enable();
			break;
		default:
			break;
		}
	}

	/**
	 * Updates sticky video title, showing default message if ad is playing.
	 * Include show name if this is an episode or clip from a program.
	 *
	 * @method updateTitle
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static updateTitle( title, show, isAd, iframeId ) {
		if ( isAd ) {
			StickyVideo.setTitle( 'Video will begin after these messages...', iframeId );
		} else if ( ! show || 0 === title.indexOf( show ) ) {
			// If show name is part of episode name, do not display show name
			StickyVideo.setTitle( title, iframeId );
		} else {
			StickyVideo.setTitle( `${show}: ${title}`, iframeId );
		}
	}

	/**
	 * Setup sticky player and listeners if this player is not yet active.
	 * Reset player paused parameter.
	 *
	 * @method activateVideo
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static activateVideo( iframeId ) {
		if ( StickyVideo.activeIFrameId !== iframeId ) {
			StickyVideo.detachCurrentVideo();
			StickyVideo.activeIFrameId = iframeId;
			StickyVideo.removeLoadIndicator( iframeId );
			StickyVideo.addVideoObserver( iframeId );

			if ( StickyVideo.anchorEnabled() ) {
				const $player = document.querySelector( `[data-displayinline-player-id="${iframeId}"]` );
				if ( $player && 'false' !== $player.dataset.displayinlineAnchor ) {
					StickyVideo.addContainerObserver( iframeId );
				}
			}
		}

		StickyVideo.activeIFramePaused = false;
	}

	/**
	 * Pause sticky player if video is currently not stuck.
	 * If user pauses the player while unsticky we don't want it to stick.
	 * If users pauses the player while sticky we don't want it to unstick.
	 *
	 * @method pauseVideo
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static pauseVideo( iframeId ) {
		if ( ! StickyVideo.isStuck( iframeId ) ) {
			StickyVideo.activeIFramePaused = true;
		}
	}

	/**
	 * Turn off all sticky video functionality for the current player.
	 *
	 * @method detatchCurrentVideo
	 */
	static detachCurrentVideo() {
		if ( StickyVideo.activeIFrameId && null !== document.querySelector( `#${StickyVideo.activeIFrameId}` ) ) {
			Messenger.sendMessage( StickyVideo.activeIFrameId, StickyVideo.messageType, 'detached' );

			// remove sticky observer
			const $video = StickyVideo.getActiveVideo();

			StickyVideo.unstick( $video );
			StickyVideo.removeVideoObserver( StickyVideo.activeIFrameId );

			customEvent.fire( $video, customEvent.STICKY_DETACHED );
			customEvent.fire( window, customEvent.STICKY_OFF, {
				target: $video,
				selector: StickyVideo.stickySelectors.element,
			});

			// remove container obserer and all anchoring styles
			if ( StickyVideo.anchorEnabled() ) {
				StickyVideo.removeContainerObserver();
				$video.classList.remove( StickyVideo.stickySelectors.states.anchored );
				$video.style.top = ''; // eslint-disable-line no-param-reassign
			}

			StickyVideo.activeIFrameId = '';
		}
	}

	/**
	 * Add intersection observer to detect when player enters and exits view.
	 *
	 * @method addVideoObserver
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static addVideoObserver( iframeId ) {
		if ( null === StickyVideo.videoObserver ) {
			const $video = StickyVideo.getVideo( iframeId );
			const $wrapper = StickyVideo.getWrapper( iframeId );
			$wrapper.dataset.alwaysObserve = 'true';

			StickyVideo.videoObserver = new InView({
				threshold: StickyVideo.intersectionRatio,
			});
			StickyVideo.videoObserver.init();
			StickyVideo.videoObserver.startWatching( $wrapper );

			StickyVideo.videoListener = StickyVideo.handleVideoIntersection.bind( this, $video );
			$wrapper.addEventListener( customEvent.IN_VIEW, StickyVideo.videoListener );
		}
	}

	/**
	 * Turn off intersection observer listener for specified player.
	 *
	 * @method removeVideoObserver
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static removeVideoObserver( iframeId ) {
		const $wrapper = StickyVideo.getWrapper( iframeId );

		StickyVideo.videoObserver.stopWatching( $wrapper );
		StickyVideo.videoObserver = null;

		$wrapper.removeEventListener( customEvent.IN_VIEW, StickyVideo.videoListener );
	}

	/**
	 * Unsticks or sticks video depending on whether player is in our out of view.
	 *
	 * @method handleVideoIntersection
	 * @param {Element} $video - Video player element
	 * @param {Object} event - Custom event fired by InView intersection observer module
	 */
	static handleVideoIntersection( $video, event ) {
		// don't toggle stickiness if video is inactive or paused
		if ( null === StickyVideo.activeIFrameId || true === StickyVideo.activeIFramePaused ) {
			return;
		}

		if ( event && event.detail ) {
			if ( event.detail.ratioInView > StickyVideo.intersectionRatio ) {
				StickyVideo.unstick( $video );
			} else {
				StickyVideo.stick( $video );
			}
		}
	}

	/**
	 * Initialize observer to check if container edges have entered the viewport
	 * If so, we need to anchor the video to the viewport so it doesn't go beyond the container.
	 *
	 * @method addContainerObserver
	 */
	static addContainerObserver() {
		if ( null === StickyVideo.containerObserver ) {
			const $pageContainer = document.querySelector( StickyVideo.pageContainerSelector );
			$pageContainer.dataset.alwaysObserve = 'true';

			StickyVideo.pageContainerListener = StickyVideo.handleContainerIntersection
				.bind( this, $pageContainer );
			$pageContainer.addEventListener( customEvent.IN_BOUNDS, StickyVideo.pageContainerListener );

			StickyVideo.containerObserver = new InBounds({
				selector: StickyVideo.pageContainerSelector,
			});
			StickyVideo.containerObserver.init();
		}
	}

	/**
	 * Remove container observer when video is deactivated
	 *
	 * @method removeContainerObserver
	 */
	static removeContainerObserver() {
		const $pageContainer = document.querySelector( StickyVideo.pageContainerSelector );

		if ( StickyVideo.containerObserver ) {
			StickyVideo.containerObserver.stopWatching( $pageContainer );
			StickyVideo.containerObserver = null;
		}

		$pageContainer.removeEventListener( customEvent.IN_BOUNDS, StickyVideo.pageContainerListener );
	}

	/**
	 * Anchor the video to the edge of the container if the container bounds have been reached.
	 * Remove the anchor if it is no longer needed and resume fixed positioning.
	 *
	 * @method handleContainerIntersection
	 * @param {Element} $pageContainer - Page container element
	 * @param {object} event - InBounds event object
	 */
	static handleContainerIntersection( $pageContainer, event ) {
		// nothing to handle if video is inactive or paused
		if ( null === StickyVideo.activeIFrameId || true === StickyVideo.activeIFramePaused ) {
			return;
		}

		// nothing to handle if sticky video is not stuck
		// if video is a mini sticky video, only anchor for lower bound.
		if ( event && event.detail ) {
			const $video = StickyVideo.getActiveVideo();
			if ( event.detail.isInBounds ) {
				StickyVideo.removeAnchor( $video );
			} else {
				StickyVideo.addAnchor( $video );
			}
		}
	}

	/**
	 * Sticks video player to right rail.
	 *
	 * @method stick
	 * @param {Element} $video - Video player element
	 */
	static stick( $video ) {
		// Bail if sticky feature is disabled.
		if ( StickyVideo.disabled ) {
			return;
		}

		if ( ! $video.classList.contains( StickyVideo.stickySelectors.states.stuck ) ) {
			Messenger.sendMessage( StickyVideo.activeIFrameId, StickyVideo.messageType, 'stuck' );

			$video.classList.remove( StickyVideo.stickySelectors.states.detatched );
			$video.classList.add( StickyVideo.stickySelectors.states.stuck );
			$video.parentNode.classList.add( StickyVideo.stickySelectors.states.container );

			customEvent.fire( window, customEvent.STICKY_ON, {
				target: $video,
				selector: StickyVideo.stickySelectors.element,
			});
		}
	}

	/**
	 * Unsticks video from right rail
	 *
	 * @method unstick
	 * @param {Element} $video - Video player element
	 */
	static unstick( $video ) {
		// Bail if sticky feature is disabled.
		if ( StickyVideo.disabled ) {
			return;
		}

		if ( $video.classList.contains( StickyVideo.stickySelectors.states.stuck ) ) {
			Messenger.sendMessage( StickyVideo.activeIFrameId, StickyVideo.messageType, 'restored' );
			$video.classList.remove( StickyVideo.stickySelectors.states.stuck );
			$video.classList.add( StickyVideo.stickySelectors.states.detatched );
			$video.parentNode.classList.remove( StickyVideo.stickySelectors.states.container );

			customEvent.fire( window, customEvent.STICKY_OFF, {
				target: $video,
				selector: StickyVideo.stickySelectors.element,
			});
		}
	}

	/**
	 * Add anchor to position sticky video absolutely at current position.
	 * Prevents it from going over header / footer.
	 *
	 * @method addAnchor
	 * @param {Element} $video - Video player element
	 */
	static addAnchor( $video ) {
		// Bail if sticky feature is disabled.
		if ( StickyVideo.disabled ) {
			return;
		}

		if ( ! $video.classList.contains( StickyVideo.stickySelectors.states.anchored ) ) {
			const bounds             = $video.getBoundingClientRect();
			const $pageContainer     = document.querySelector( StickyVideo.pageContainerSelector );
			const containerBounds    = $pageContainer.getBoundingClientRect();
			let containerMarginTop   = getComputedStyle( $pageContainer ).getPropertyValue( 'margin-top' );
			containerMarginTop = parseInt( containerMarginTop.replace( 'px', '' ), 10 );
			const containerOffsetMin = containerBounds.top - containerMarginTop + window.pageYOffset;
			const containerOffsetMax = containerBounds.bottom + window.pageYOffset - bounds.height;
			let offset               = 0;

			if ( ! $video.classList.contains( StickyVideo.stickySelectors.states.anchored ) ) {
				offset = bounds.top + window.pageYOffset;

				// min offset to prevent sticky video from overlapping header ad or footer
				offset = Math.max( offset, containerOffsetMin );
				offset = Math.min( offset, containerOffsetMax );

				$video.style.top = `${offset}px`;	// eslint-disable-line no-param-reassign
				$video.classList.add( StickyVideo.stickySelectors.states.anchored );

				// set position: static for cascaded container nodes.
				// TO BE REMOVED WHEN STICKY PLAYER ANCHORS TO THE BOTTOM.
				const playerId = $video.getAttribute( 'id' ).replace( '__sticky', '' );
				const $containers = document.querySelectorAll( `[data-container-of-video="${playerId}"]` );
				[].forEach.call( $containers, ( $container ) => {
					$container.classList.add( StickyVideo.stickySelectors.states.cascadedContainer );
				});

				customEvent.fire( window, customEvent.STICKY_OFF, {
					target: $video,
					selector: StickyVideo.stickySelectors.element,
				});
			}
		}
	}

	/**
	 * Remove anchor and resume fixed positioning of sticky video player
	 *
	 * @method removeAnchor
	 * @param {Element} $video - Video player element
	 */
	static removeAnchor( $video ) {
		// Bail if sticky feature is disabled.
		if ( StickyVideo.disabled ) {
			return;
		}

		if ( $video.classList.contains( StickyVideo.stickySelectors.states.anchored ) ) {
			$video.style.top = '';	// eslint-disable-line no-param-reassign
			$video.classList.remove( StickyVideo.stickySelectors.states.anchored );

			// set position: static for cascaded container nodes.
			// TO BE REMOVED WHEN STICKY PLAYER ANCHORS TO THE BOTTOM.
			const playerId = $video.getAttribute( 'id' ).replace( '__sticky', '' );
			const $containers = document.querySelectorAll( `[data-container-of-video="${playerId}"]` );
			[].forEach.call( $containers, ( $container ) => {
				$container.classList.add( StickyVideo.stickySelectors.states.cascadedContainer );
			});

			customEvent.fire( window, customEvent.STICKY_ON, {
				target: $video,
				selector: StickyVideo.stickySelectors.element,
			});
		}
	}

	/**
	 * Stops the video and unsticks the player if user clicks the close button
	 *
	 * @method close
	 */
	static close( evt ) {
		gn_analytics.Analytics.track(['adobe', 'ga'], {
			action: 'close sticky video',
			data: {
				'video.stickyclosed': '1',
			},
			target: evt.currentTarget,
		});
		StickyVideo.detachCurrentVideo();
	}

	/**
	 * Sends a message to the video player on click.
	 *
	 * @method sendVideoAction
	 */
	static sendVideoAction( evt ) {
		if ( evt.currentTarget.dataset.videoAction ) {
			Messenger.sendMessage( StickyVideo.activeIFrameId,
				StickyVideo.messageType,
				evt.currentTarget.dataset.videoAction );
		}
	}

	/**
	 * Removes loading spinner once video (or ad) has loaded.
	 *
	 * @method removeLoadIndicator
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static removeLoadIndicator( iframeId ) {
		const $video = StickyVideo.getVideo( iframeId );

		if ( $video ) {
			$video.classList.remove( StickyVideo.stickySelectors.states.loading );
		}
	}

	/**
	 * Updates the text of the title bar above the sticky player.
	 *
	 * @method setTitle
	 * @param {string} title - text to place in the title bar
	 * @param {string} iframeId - ID of video iframe in question
	 */
	static setTitle( title, iframeId ) {
		const $video = StickyVideo.getVideo( iframeId );

		if ( $video ) {
			const $titleNode = $video.querySelector( `.${StickyVideo.stickySelectors.title}` );
			$titleNode.textContent = title;
		}
	}

	/**
	 * Show / hide mute unmute buttons.
	 *
	 * @method updateVolume
	 * @param {object} data
	 */
	static updateVolume( data ) {
		const $video = StickyVideo.getVideo( data.iframeId );
		if ( $video ) {
			if ( data.muted ) {
				$video.classList.add( StickyVideo.stickySelectors.states.muted );
			} else {
				$video.classList.remove( StickyVideo.stickySelectors.states.muted );
			}
		}
	}

	/**
	 * Bring the video in view.
	 */
	static focusVideo() {
		const $video = StickyVideo.getActiveVideo();
		if ( $video && $video.parentNode ) {
			const videoRect = $video.parentNode.getBoundingClientRect();
			const centeredPosY = ( window.innerHeight - videoRect.height ) * 0.5;
			window.scrollTo( window.scrollX, window.scrollY + videoRect.top - centeredPosY );
		}
	}

	/**
	 * Disable sticky video
	 */
	static disable() {
		StickyVideo.disabled = true;
	}

	/**
	 * Enable sticky video
	 */
	static enable() {
		StickyVideo.disabled = false;
	}

	/**
	 * Gets currently active video element.
	 *
	 * @method getActiveVideo
	 * @returns {Element} Video player element
	 */
	static getActiveVideo() {
		return StickyVideo.getVideo( StickyVideo.activeIFrameId );
	}

	/**
	 * Gets specified video player element.
	 *
	 * @method getVideo
	 * @param {string} iframeId - ID of video iframe in question
	 * @returns {Element} Video player element
	 */
	static getVideo( iframeId ) {
		if ( iframeId ) {
			return document.querySelector( `#${iframeId}__sticky` );
		}

		return false;
	}

	/**
	 * Get's the CSS selector for the specified video player's parent element.
	 * Useful because we need to add our Intersection Observer to the player's parent.
	 *
	 * @method getWrapperSelector
	 * @param {string} iframeId - ID of video iframe in question
	 * @param {string} CSS selector to identify the player's parent element.
	 */
	static getWrapperSelector( iframeId ) {
		if ( iframeId ) {
			return `[${StickyVideo.stickyAttribute}="${iframeId}"]`;
		}

		return false;
	}

	/**
	 * Get's the CSS selector for the specified video player's parent element.
	 * Useful because we need to add our Intersection Observer to the player's parent.
	 *
	 * @method getWrapper
	 * @param {string} iframeId - ID of video iframe in question
	 * @param {string} CSS selector to identify the player's parent element.
	 */
	static getWrapper( iframeId ) {
		const wrapperSelector = StickyVideo.getWrapperSelector( iframeId );
		let $wrapper = document.querySelector( wrapperSelector );

		// if data-displayinline-container is set, watch the container instead of video iframe
		if ( $wrapper.dataset.displayinlineContainer ) {
			$wrapper = document.querySelector( `[data-container-id="${$wrapper.dataset.displayinlineContainer}"]` );
		}

		return $wrapper;
	}

	/**
	 * Get the SVG sprite path from gnca_settings object
	 *
	 * @method getSVGSpritePath
	 * @return {string} file path the SVG sprite.
	 */
	static getSVGSpritePath() {
		/* eslint-disable camelcase */
		if ( 'undefined' !== typeof ( gnca_settings )
			&& gnca_settings.svg_sprite_uri
			&& gnca_settings.svg_sprite_uri ) {
			return gnca_settings.svg_sprite_uri;
		}

		return '';
		/* eslint-enable camelcase */
	}

	/**
	 * Determines whether sticky video should be enabled on this page based on global settings.
	 *
	 * @method stickyEnabled
	 * @return {boolean} T/F depending on whether or not sticky video is enabled.
	 */
	static stickyEnabled() {
		/* eslint-disable camelcase */
		if ( 'undefined' !== typeof ( gnca_settings )
			&& gnca_settings.video_settings
			&& gnca_settings.video_settings.sticky_enabled ) {
			return Boolean( gnca_settings.video_settings.sticky_enabled );
		}
		/* eslint-enable camelcase */

		return false;
	}

	/**
	 * Determines whether sticky video anchoring is enabled on this page based on global settings.
	 *
	 * @method anchorEnabled
	 * @return {boolean} T/F depending on whether or not anchor video is enabled.
	 */
	static anchorEnabled() {
		/* eslint-disable camelcase */
		if ( 'undefined' !== typeof ( gnca_settings )
			&& gnca_settings.video_settings
			&& gnca_settings.video_settings.anchor_enabled ) {
			return Boolean( gnca_settings.video_settings.anchor_enabled );
		}
		/* eslint-enable camelcase */

		return false;
	}

	/**
	 * Determines if player in question is currently stickied.
	 *
	 * @method isStuck
	 * @param {string} iframeId - ID of video iframe in question
	 * @param {boolean} T/F depending on whether or not specified player is stickied.
	 */
	static isStuck( iframeId ) {
		return StickyVideo.getVideo( iframeId ).classList
			.contains( StickyVideo.stickySelectors.states.stuck );
	}
}

export default StickyVideo;