if ( typeof fcaPcOptions === 'object' && fcaPcOptions.video_enabled ) {

	class EventEmitter {

		constructor() {
			this.events = {}
		}

		on(event, listener) {
			if (typeof this.events[event] !== 'object') {
				this.events[event] = []
			}
			this.events[event].push(listener)
			return () => this.removeListener(event, listener)
		}

		removeListener(event, listener) {
			if (typeof this.events[event] === 'object') {
				const idx = this.events[event].indexOf(listener)
				if (idx > -1) {
					this.events[event].splice(idx, 1)
				}
			}
		}

		emit(event, ...args) {
			if (typeof this.events[event] === 'object') {
				this.events[event].forEach(listener => listener.apply(this, args))
			}
		}

		once(event, listener) {
			const remove = this.on(event, (...args) => {
				remove()
				listener.apply(this, args)
			})
		}
	}

	class FCA_PC_Video extends EventEmitter {

		constructor(selector) {
			super()

			this.video_ready = false

			if (typeof selector === undefined) {
				return
			}

			this.element = selector
			this.init()

		}

		init() {
			
			this.setup_events()
			this.type = this.video_type()
			this.load_api()
		}

		load_api() {
			switch (this.type) {
				case 'YOUTUBE':
					this.api_youtube_load()
					break
				case 'WISTIA':
					this.api_wistia_load()
					break
				case 'VIMEO':
					this.api_vimeo_load()
					break
			}
		}

		setup_events() {
			this.on( 'api_youtube_loaded', this.api_youtube_setup )
			this.on( 'api_vimeo_loaded', this.api_vimeo_setup )
			this.on( 'api_wistia_loaded', this.api_wistia_setup )
		}

		video_type() {
			let src = this.element.attr('src')

			if (src === '') {
				this.revoke( 'pixel cat video: video link not found.' )
				return false
			}

			if (src.indexOf('youtube.com') > -1) return 'YOUTUBE'
			if (src.indexOf('vimeo.com') > -1) return 'VIMEO'
			if (src.indexOf('fast.wistia.com') > -1) return 'WISTIA'
		}

		revoke( message ) {
			if ( fcaPcOptions.debug ) {
				console.log( message )
				console.log( 'pixel cat video: revoked ')
			}
			// Do some code that revoke video JS here.
		}

		//VIMEO

		api_vimeo_load() {
			jQuery.getScript( 'https://player.vimeo.com/api/player.js', () => {
				this.emit( 'api_vimeo_loaded' )
			} )
		}

		api_vimeo_setup() {
			let player_dom = this.element[0]
			try {
				this.api = new Vimeo.Player(player_dom)
				this.api.ready().then( () => {
					this.api_vimeo_ready()
				} )
			} catch ( e ) {
				if ( fcaPcOptions.debug)
					console.log( e.message )
				return
			}
		}

		api_vimeo_ready() {
			if (fcaPcOptions.debug) {
				console.log( 'Pixel Cat video: Vimeo video ready' )
			}

			this.video_ready = true

			this.api.getVideoId().then( id => {
				this.video_id = id
			} )

			this.api.getVideoTitle().then( title => {
				this.title = title
			} )

			this.api.getVideoUrl().then( url => {
				this.url = url
			} )

			this.api.getDuration().then( duration => {
				this.duration = duration
			} )

			this.events_triggered = {}

			this.api_vimeo_state_change()
		}

		api_vimeo_state_change() {
			this.api.on( 'play', event => {
				this.trigger_event( 'VideoPlay' )
				this.timer = setInterval( this.track_progress.bind(this), 1000 )
			} )

			this.api.on( 'pause', event => {
				this.trigger_event( 'VideoPause', { percentage_watched: this.percentage_watched() + '%' } )
				clearInterval( this.timer )
			} )

			this.api.on( 'ended', event => {
				this.trigger_event( 'VideoWatchToEnd' )
				clearInterval( this.timer )
			} )
		}

		//WISTIA

		api_wistia_load() {
			jQuery.getScript( '//fast.wistia.net/assets/external/E-v1.js', () => {
				this.emit( 'api_wistia_loaded' )
			} )
		}

		api_wistia_setup() {

			let player_dom = this.element

			let video_src = player_dom.attr('src')

			if (typeof video_src === 'undefined') {
				return
			}

			//GET VIDEO ID FROM URL

			const pattern = /(https:\/\/fast\.wistia\.com\/embed\/medias)\/(.*)\.jsonp/

			let match = video_src.match(pattern)

			if (match === null) {

				if ( fcaPcOptions.debug ) {
					console.log('no video id match')
				}

				return
			}

			this.url = match[1]

			let video_id = match[2]

			if ( typeof video_id === 'undefined' ) {
				if ( fcaPcOptions.debug ) {
					console.log ( 'pixel cat video: wistia video_id not found.' )
				}
				return
			}

			window._wq = window._wq || []

			this.api = window._wq

			this.api.push( {
				id: video_id,
				onReady: this.api_wistia_ready.bind(this)
			} )
		}

		api_wistia_ready( video ) {

			if ( fcaPcOptions.debug ) {
				console.log ( 'pixel cat video: wistia video ready.' )
			}

			this.video_ready = true
			this.api = video

			this.video_id = video.data.media.hashedId
			this.title = video.data.media.name !== undefined ? video.data.media.name : 'Untitled'
			this.url = this.url + '/' + this.video_id
			this.events_triggered = {}
			this.api_wistia_state_change.bind(this)()
		}

		api_wistia_state_change() {
			this.api.bind( 'play', event => {
				this.trigger_event( 'VideoPlay' )
			} )

			this.api.bind( 'pause', event => {
				this.trigger_event( 'VideoPause', { percentage_watched: this.percentage_watched() + '%' } )
			} )

			this.api.bind( 'percentwatchedchanged', ( percent, lastPercent ) => {
				this.track_progress()
			} )

			this.api.bind( 'end', event => {
				this.trigger_event( 'VideoWatchToEnd' )
			} )
		}

		//YOUTUBE

		api_youtube_load() {
			this.load_async_script( 'https://www.youtube.com/iframe_api' )
		}

		api_youtube_setup() {
			let player_dom = this.element[0]
			this.api = new YT.Player(player_dom, {
				events: {
					'onReady': this.api_youtube_ready.bind(this),
					'onStateChange': this.api_youtube_state_change.bind(this)
				}
			})
		}

		api_youtube_ready( event ) {

			if ( fcaPcOptions.debug ) {
				console.log( 'pixel cat video: youtube video ready')
			}

			// @todo: we will need to build this one in future to make sure the video is ready to use the object
			this.video_ready = true
			this.data = this.api.getVideoData()
			this.video_id = this.data.video_id
			this.title = this.data.title
			this.url = this.api.getVideoUrl()

			this.events_triggered = {}
		}

		api_youtube_state_change( event ) {
			if ( fcaPcOptions.debug ) {
				console.log( event )
			}

			switch ( event.data ) {
				case 0:
					// end video
					this.trigger_event( 'VideoWatchToEnd' )
					clearInterval( this.timer )
					break

				case 1:
					// play video
					this.trigger_event( 'VideoPlay' )
					// Since we check progress using range: ( percent >= 10 && percent < 25 )
					// So we do not need to set interval too fast. 1 - 2 seconds should be fine
					this.timer = setInterval( this.track_progress.bind(this), 1000 )
					break

				case 2:
					// pause video
					this.trigger_event( 'VideoPause',  { percentage_watched: this.percentage_watched() + '%' } )
					clearInterval( this.timer )
					break
			}
		}

		video_youtube_end() {
			if ( fcaPcOptions.debug ) {
				console.log( 'end' )
			}
		}

		load_async_script( url ) {
			let new_script = document.createElement('script')
			let first_script = document.getElementsByTagName('script')[0]
		
			new_script.src = url

	        first_script.parentNode.insertBefore(new_script, first_script)

			if ( fcaPcOptions.debug ) {
				console.log('pixel cat video: ' + url + ' has been loaded.')
			}
		}

		track_progress() {
			switch( this.video_type() ) {
				case 'YOUTUBE':
				case 'VIMEO':
				case 'WISTIA':
					this.video_track_progress()
					break

				// Other cases
			}
		}

		video_track_progress() {
			let percent = this.percentage_watched()

			if ( fcaPcOptions.debug ) {
				console.log( this.percentage_watched() )
			}

			// Need to cover all the cases and reduce interval time -> better performance
			// Use switch here for better code readable
			switch ( true ) {
				// 10% milestone
				case ( percent >= 10 && percent < 25 ):
					this.trigger_event('VideoWatch10Percent')
					break

				// 25% milestone
				case ( percent >= 25 && percent < 50 ):
					this.trigger_event('VideoWatch25Percent')
					break

				case ( percent >= 50 && percent < 75 ):
					this.trigger_event('VideoWatch50Percent')
					break

				case ( percent >= 75 && percent < 90 ):
					this.trigger_event('VideoWatch75Percent')
					break

				case ( percent >= 90 && percent < 100 ):
					this.trigger_event('VideoWatch90Percent')
					break
			}
		}

		video_params() {
			return {
				video_title: this.title,
				video_url: this.url,
				video_id: this.video_id
			}
		}

		percentage_watched() {
			switch( this.type ) {
				case 'YOUTUBE':
					return  Math.round( this.api.getCurrentTime() / this.api.getDuration() * 100 )
				
				case 'VIMEO':
					this.api.getCurrentTime().then( current_time => {
						this.current_time = current_time
					} )
					return  Math.round( this.current_time / this.duration * 100 )
					
				case 'WISTIA':
					return Math.round( this.api.time() / this.api.duration() * 100 )

				default:
					return false
			}
		}

		trigger_event( action, additional_params = {} ) {

			if ( this.events_triggered[action] ) { 
				return
			}

			let params = Object.assign( {}, this.video_params(), additional_params )

			this.emit( 'pixel_event', 'trackCustom', action, params )

			// Add exception for VideoPause event
			if (  action !== 'VideoPause' ) {
				this.events_triggered[action] = true
			}
		}


	}

	FCA_PC_Video.prototype.__proto__ = EventEmitter.prototype;

	function onYouTubeIframeAPIReady() {

		fcaPcVideos.forEach(video => {
			if (video.type !== 'YOUTUBE') {
				return
			}

			video.emit('api_youtube_loaded')	
		})
		
	}

	window.fcaPcVideos = [];

	// detect all videos on the page
	function detect_videos() {

		let videos = [];

		jQuery( 'iframe' ).each(function () {
			var char = jQuery(this)[0].src.includes( '?' ) ? '&' : '?'
			jQuery(this)[0].src = jQuery(this)[0].src + char + 'enablejsapi=1'
			videos.push(jQuery(this))
		})

		jQuery( 'script' ).each(function () {

			let src = jQuery(this).attr('src')

			if (typeof src === 'undefined') {
				return
			}

			if (src.indexOf('https://fast.wistia.com/embed/medias/') === -1) {
				return
			}

			videos.push(jQuery(this))

		})

		if (videos.length === 0) {

			if ( fcaPcOptions.debug ) {
				console.log('No videos detected')	
			}

			return
		}

		videos.forEach(function (video) {
			window.fcaPcVideos.push(new FCA_PC_Video(video))
		})

		
	}


	detect_videos()
	
}
