/*!
 * Name    : Video Worker (wrapper for Youtube, Vimeo and Local videos)
 * Version : 1.2.1
 * Author  : _nK https://nkdev.info
 * GitHub  : https://github.com/nk-o/jarallax
 */
(function (window) {
    'use strict';

    // Extend like jQuery.extend
    function extend (out) {
        out = out || {};
        for (var i = 1; i < arguments.length; i++) {
            if (!arguments[i]) {
                continue;
            }
            for (var key in arguments[i]) {
                if (arguments[i].hasOwnProperty(key)) {
                    out[key] = arguments[i][key];
                }
            }
        }
        return out;
    }

    // Deferred
    // thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery
    function Deferred () {
        this._done = [];
        this._fail = [];
    }
    Deferred.prototype = {
        execute: function (list, args) {
            var i = list.length;
            args = Array.prototype.slice.call(args);
            while(i--) {
                list[i].apply(null, args);
            }
        },
        resolve: function () {
            this.execute(this._done, arguments);
        },
        reject: function () {
            this.execute(this._fail, arguments);
        },
        done: function (callback) {
            this._done.push(callback);
        },
        fail: function (callback) {
            this._fail.push(callback);
        }
    };

    // init events
    function addEventListener (el, eventName, handler) {
        if (el.addEventListener) {
            el.addEventListener(eventName, handler);
        } else {
            el.attachEvent('on' + eventName, function (){
                handler.call(el);
            });
        }
    }

    var VideoWorker = (function () {
        var ID = 0;

        function VideoWorker_inner (url, options) {
            var _this = this;

            _this.url = url;

            _this.options_default = {
                autoplay: 1,
                loop: 1,
                mute: 1,
                controls: 0,

                // start / end video time in ms
                startTime: 0,
                endTime: 0
            };

            _this.options = extend({}, _this.options_default, options);

            // check URL
            _this.videoID = _this.parseURL(url);

            // init
            if(_this.videoID) {
                _this.ID = ID++;
                _this.loadAPI();
                _this.init();
            }
        }

        return VideoWorker_inner;
    }());

    VideoWorker.prototype.parseURL = function (url) {
        // parse youtube ID
        function getYoutubeID (ytUrl) {
            var regExp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
            var match = ytUrl.match(regExp);
            return match && match[1].length === 11 ? match[1] : false;
        }

        // parse vimeo ID
        function getVimeoID (vmUrl) {
            var regExp = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
            var match = vmUrl.match(regExp);
            return match && match[3] ? match[3] : false;
        }

        // parse local string
        function getLocalVideos (locUrl) {
            var videoFormats = locUrl.split(/,(?=mp4\:|webm\:|ogv\:|ogg\:)/);
            var result = {};
            var ready = 0;
            for(var k = 0; k < videoFormats.length; k++) {
                var match = videoFormats[k].match(/^(mp4|webm|ogv|ogg)\:(.*)/);
                if(match && match[1] && match[2]) {
                    result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];
                    ready = 1;
                }
            }
            return ready ? result : false;
        }

        var Youtube = getYoutubeID(url);
        var Vimeo = getVimeoID(url);
        var Local = getLocalVideos(url);

        if(Youtube) {
            this.type = 'youtube';
            return Youtube;
        } else if (Vimeo) {
            this.type = 'vimeo';
            return Vimeo;
        } else if (Local) {
            this.type = 'local';
            return Local;
        }

        return false;
    };

    VideoWorker.prototype.isValid = function () {
        return !!this.videoID;
    };

    // events
    VideoWorker.prototype.on = function (name, callback) {
        this.userEventsList = this.userEventsList || [];

        // add new callback in events list
        (this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);
    };
    VideoWorker.prototype.off = function (name, callback) {
        if(!this.userEventsList || !this.userEventsList[name]) {
            return;
        }

        if(!callback) {
            delete this.userEventsList[name];
        } else {
            for(var k = 0; k < this.userEventsList[name].length; k++) {
                if(this.userEventsList[name][k] === callback) {
                    this.userEventsList[name][k] = false;
                }
            }
        }
    };
    VideoWorker.prototype.fire = function (name) {
        var args = [].slice.call(arguments, 1);
        if(this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {
            for(var k in this.userEventsList[name]) {
                // call with all arguments
                if(this.userEventsList[name][k]) {
                    this.userEventsList[name][k].apply(this, args);
                }
            }
        }
    };

    VideoWorker.prototype.play = function (start) {
        var _this = this;
        if(!_this.player) {
            return;
        }

        if(_this.type === 'youtube' && _this.player.playVideo) {
            if(typeof start !== 'undefined') {
                _this.player.seekTo(start || 0);
            }
            _this.player.playVideo();
        }

        if(_this.type === 'vimeo') {
            if (typeof start !== 'undefined') {
                _this.player.setCurrentTime(start);
            }
            _this.player.getPaused().then(function(paused) {
                if (paused) {
                    _this.player.play();
                }
            });
        }

        if(_this.type === 'local') {
            if(typeof start !== 'undefined') {
                _this.player.currentTime = start;
            }
            _this.player.play();
        }
    };

    VideoWorker.prototype.pause = function () {
        if(!this.player) {
            return;
        }

        if(this.type === 'youtube' && this.player.pauseVideo) {
            this.player.pauseVideo();
        }

        if(this.type === 'vimeo') {
            this.player.pause();
        }

        if(this.type === 'local') {
            this.player.pause();
        }
    };

    VideoWorker.prototype.getImageURL = function (callback) {
        var _this = this;

        if(_this.videoImage) {
            callback(_this.videoImage);
            return;
        }

        if(_this.type === 'youtube') {
            var availableSizes = [
                'maxresdefault',
                'sddefault',
                'hqdefault',
                '0'
            ];
            var step = 0;

            var tempImg = new Image();
            tempImg.onload = function () {
                // if no thumbnail, youtube add their own image with width = 120px
                if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {
                    // ok
                    _this.videoImage = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
                    callback(_this.videoImage);
                } else {
                    // try another size
                    step++;
                    this.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
                }
            };
            tempImg.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
        }

        if(_this.type === 'vimeo') {
            var request = new XMLHttpRequest();
            request.open('GET', 'https://vimeo.com/api/v2/video/' + _this.videoID + '.json', true);
            request.onreadystatechange = function () {
                if (this.readyState === 4) {
                    if (this.status >= 200 && this.status < 400) {
                        // Success!
                        var response = JSON.parse(this.responseText);
                        _this.videoImage = response[0].thumbnail_large;
                        callback(_this.videoImage);
                    } else {
                        // Error :(
                    }
                }
            };
            request.send();
            request = null;
        }
    };

    VideoWorker.prototype.getIframe = function (callback) {
        var _this = this;

        // return generated iframe
        if(_this.$iframe) {
            callback(_this.$iframe);
            return;
        }

        // generate new iframe
        _this.onAPIready(function () {
            var hiddenDiv;
            if(!_this.$iframe) {
                hiddenDiv = document.createElement('div');
                hiddenDiv.style.display = 'none';
            }

            // Youtube
            if(_this.type === 'youtube') {
                _this.playerOptions = {};
                _this.playerOptions.videoId = _this.videoID;
                _this.playerOptions.playerVars = {
                    autohide: 1,
                    rel: 0,
                    autoplay: 0
                };

                // hide controls
                if(!_this.options.controls) {
                    _this.playerOptions.playerVars.iv_load_policy = 3;
                    _this.playerOptions.playerVars.modestbranding = 1;
                    _this.playerOptions.playerVars.controls = 0;
                    _this.playerOptions.playerVars.showinfo = 0;
                    _this.playerOptions.playerVars.disablekb = 1;
                }

                // events
                var ytStarted;
                var ytProgressInterval;
                _this.playerOptions.events = {
                    onReady: function (e) {
                        // mute
                        if(_this.options.mute) {
                            e.target.mute();
                        }
                        // autoplay
                        if(_this.options.autoplay) {
                            _this.play(_this.options.startTime);
                        }
                        _this.fire('ready', e);
                    },
                    onStateChange: function (e) {
                        // loop
                        if(_this.options.loop && e.data === YT.PlayerState.ENDED) {
                            _this.play(_this.options.startTime);
                        }
                        if(!ytStarted && e.data === YT.PlayerState.PLAYING) {
                            ytStarted = 1;
                            _this.fire('started', e);
                        }
                        if(e.data === YT.PlayerState.PLAYING) {
                            _this.fire('play', e);
                        }
                        if(e.data === YT.PlayerState.PAUSED) {
                            _this.fire('pause', e);
                        }
                        if(e.data === YT.PlayerState.ENDED) {
                            _this.fire('end', e);
                        }

                        // check for end of video and play again or stop
                        if(_this.options.endTime) {
                            if(e.data === YT.PlayerState.PLAYING) {
                                ytProgressInterval = setInterval(function () {
                                    if(_this.options.endTime && _this.player.getCurrentTime() >= _this.options.endTime) {
                                        if(_this.options.loop) {
                                            _this.play(_this.options.startTime);
                                        } else {
                                            _this.pause();
                                        }
                                    }
                                }, 150);
                            } else {
                                clearInterval(ytProgressInterval);
                            }
                        }
                    }
                };

                var firstInit = !_this.$iframe;
                if(firstInit) {
                    var div = document.createElement('div');
                    div.setAttribute('id', _this.playerID);
                    hiddenDiv.appendChild(div);
                    document.body.appendChild(hiddenDiv);
                }
                _this.player = _this.player || new window.YT.Player(_this.playerID, _this.playerOptions);
                if(firstInit) {
                    _this.$iframe = document.getElementById(_this.playerID);

                    // get video width and height
                    _this.videoWidth = parseInt(_this.$iframe.getAttribute('width'), 10) || 1280;
                    _this.videoHeight = parseInt(_this.$iframe.getAttribute('height'), 10) || 720;
                }
            }

            // Vimeo
            if(_this.type === 'vimeo') {
                _this.playerOptions = '';

                _this.playerOptions += 'player_id=' + _this.playerID;
                _this.playerOptions += '&autopause=0';

                // hide controls
                if(!_this.options.controls) {
                    _this.playerOptions += '&badge=0&byline=0&portrait=0&title=0';
                }

                // autoplay
                _this.playerOptions += '&autoplay=' + (_this.options.autoplay ? '1' : '0');

                // loop
                _this.playerOptions += '&loop=' + (_this.options.loop ? 1 : 0);

                if(!_this.$iframe) {
                    _this.$iframe = document.createElement('iframe');
                    _this.$iframe.setAttribute('id', _this.playerID);
                    _this.$iframe.setAttribute('src', 'https://player.vimeo.com/video/' + _this.videoID + '?' + _this.playerOptions);
                    _this.$iframe.setAttribute('frameborder', '0');
                    hiddenDiv.appendChild(_this.$iframe);
                    document.body.appendChild(hiddenDiv);
                }

                _this.player = _this.player || new Vimeo.Player(_this.$iframe);

                // get video width and height
                _this.player.getVideoWidth().then(function (width) {
                    _this.videoWidth = width || 1280;
                });
                _this.player.getVideoHeight().then(function (height) {
                    _this.videoHeight = height || 720;
                });

                // mute
                _this.player.setVolume(_this.options.mute ? 0 : 100);

                var vmStarted;
                _this.player.on('timeupdate', function (e) {
                    if(!vmStarted) {
                        _this.fire('started', e);
                    }
                    vmStarted = 1;

                    // check for end of video and play again or stop
                    if(_this.options.endTime) {
                        if(_this.options.endTime && e.seconds >= _this.options.endTime) {
                            if(_this.options.loop) {
                                _this.play(_this.options.startTime);
                            } else {
                                _this.pause();
                            }
                        }
                    }
                });
                _this.player.on('play', function (e) {
                    _this.fire('play', e);

                    // check for the start time and start with it
                    if(_this.options.startTime && e.seconds === 0) {
                        _this.play(_this.options.startTime);
                    }
                });
                _this.player.on('pause', function (e) {
                    _this.fire('pause', e);
                });
                _this.player.on('ended', function (e) {
                    _this.fire('end', e);
                });
                _this.player.on('loaded', function (e) {
                    _this.fire('ready', e);
                });
            }

            // Local
            function addSourceToLocal (element, src, type) {
                var source = document.createElement('source');
                source.src = src;
                source.type = type;
                element.appendChild(source);
            }
            if(_this.type === 'local') {
                if(!_this.$iframe) {
                    _this.$iframe = document.createElement('video');

                    // mute
                    if(_this.options.mute) {
                        _this.$iframe.muted = true;
                    }

                    // loop
                    if(_this.options.loop) {
                        _this.$iframe.loop = true;
                    }

                    _this.$iframe.setAttribute('id', _this.playerID);
                    hiddenDiv.appendChild(_this.$iframe);
                    document.body.appendChild(hiddenDiv);

                    for(var k in _this.videoID) {
                        addSourceToLocal(_this.$iframe, _this.videoID[k], 'video/' + k);
                    }
                }

                _this.player = _this.player || _this.$iframe;

                var locStarted;
                addEventListener(_this.player, 'playing', function (e) {
                    if(!locStarted) {
                        _this.fire('started', e);
                    }
                    locStarted = 1;
                });
                addEventListener(_this.player, 'timeupdate', function () {
                    // check for end of video and play again or stop
                    if(_this.options.endTime) {
                        if(_this.options.endTime && this.currentTime >= _this.options.endTime) {
                            if(_this.options.loop) {
                                _this.play(_this.options.startTime);
                            } else {
                                _this.pause();
                            }
                        }
                    }
                });
                addEventListener(_this.player, 'play', function (e) {
                    _this.fire('play', e);
                });
                addEventListener(_this.player, 'pause', function (e) {
                    _this.fire('pause', e);
                });
                addEventListener(_this.player, 'ended', function (e) {
                    _this.fire('end', e);
                });
                addEventListener(_this.player, 'loadedmetadata', function () {
                    // get video width and height
                    _this.videoWidth = this.videoWidth || 1280;
                    _this.videoHeight = this.videoHeight || 720;

                    _this.fire('ready');

                    // autoplay
                    if(_this.options.autoplay) {
                        _this.play(_this.options.startTime);
                    }
                });
            }

            callback(_this.$iframe);
        });
    };

    VideoWorker.prototype.init = function () {
        var _this = this;

        _this.playerID = 'VideoWorker-' + _this.ID;
    };

    var YoutubeAPIadded = 0;
    var VimeoAPIadded = 0;
    VideoWorker.prototype.loadAPI = function () {
        var _this = this;

        if(YoutubeAPIadded && VimeoAPIadded) {
            return;
        }

        var src = '';

        // load Youtube API
        if(_this.type === 'youtube' && !YoutubeAPIadded) {
            YoutubeAPIadded = 1;
            src = '//www.youtube.com/iframe_api';
        }

        // load Vimeo API
        if(_this.type === 'vimeo' && !VimeoAPIadded) {
            VimeoAPIadded = 1;
            src = '//player.vimeo.com/api/player.js';
        }

        if(!src) {
            return;
        }

        if (window.location.origin === 'file://') {
            src = 'http:' + src;
        }

        // add script in head section
        var tag = document.createElement('script');
        var head = document.getElementsByTagName('head')[0];
        tag.src = src;

        head.appendChild(tag);

        head = null;
        tag = null;
    };

    var loadingYoutubePlayer = 0;
    var loadingVimeoPlayer = 0;
    var loadingYoutubeDeffer = new Deferred();
    var loadingVimeoDeffer = new Deferred();
    VideoWorker.prototype.onAPIready = function (callback) {
        var _this = this;

        // Youtube
        if(_this.type === 'youtube') {
            // Listen for global YT player callback
            if ((typeof YT === 'undefined' || YT.loaded === 0) && !loadingYoutubePlayer) {
                // Prevents Ready event from being called twice
                loadingYoutubePlayer = 1;

                // Creates deferred so, other players know when to wait.
                window.onYouTubeIframeAPIReady = function () {
                    window.onYouTubeIframeAPIReady = null;
                    loadingYoutubeDeffer.resolve('done');
                    callback();
                };
            } else if (typeof YT === 'object' && YT.loaded === 1)  {
                callback();
            } else {
                loadingYoutubeDeffer.done(function () {
                    callback();
                });
            }
        }

        // Vimeo
        if(_this.type === 'vimeo') {
            if(typeof Vimeo === 'undefined' && !loadingVimeoPlayer) {
                loadingVimeoPlayer = 1;
                var vimeo_interval = setInterval(function () {
                    if(typeof Vimeo !== 'undefined') {
                        clearInterval(vimeo_interval);
                        loadingVimeoDeffer.resolve('done');
                        callback();
                    }
                }, 20);
            } else if (typeof Vimeo !== 'undefined') {
                callback();
            } else {
                loadingVimeoDeffer.done(function () {
                    callback();
                });
            }
        }

        // Local
        if(_this.type === 'local') {
            callback();
        }
    };

    window.VideoWorker = VideoWorker;
}(window));



/*!
 * Name    : Video Background Extension for Jarallax
 * Version : 1.0.0
 * Author  : _nK http://nkdev.info
 * GitHub  : https://github.com/nk-o/jarallax
 */
(function () {
    'use strict';

    if(typeof jarallax === 'undefined') {
        return;
    }

    var Jarallax = jarallax.constructor;

    // append video after init Jarallax
    var def_init = Jarallax.prototype.init;
    Jarallax.prototype.init = function () {
        var _this = this;

        def_init.apply(_this);

        if(_this.video) {
            _this.video.getIframe(function (iframe) {
                var $parent = iframe.parentNode;
                _this.css(iframe, {
                    position: _this.image.position,
                    top: '0px', left: '0px', right: '0px', bottom: '0px',
                    width: '100%',
                    height: '100%',
                    maxWidth: 'none',
                    maxHeight: 'none',
                    visibility: 'hidden',
                    margin: 0,
                    zIndex: -1
                });
                _this.$video = iframe;
                _this.image.$container.appendChild(iframe);

                // remove parent iframe element (created by VideoWorker)
                $parent.parentNode.removeChild($parent);
            });
        }
    };

    // cover video
    var def_coverImage = Jarallax.prototype.coverImage;
    Jarallax.prototype.coverImage = function () {
        var _this = this;

        def_coverImage.apply(_this);

        // add video height over than need to hide controls
        if(_this.video && _this.image.$item.nodeName === 'IFRAME') {
            _this.css(_this.image.$item, {
                height: _this.image.$item.getBoundingClientRect().height + 400 + 'px',
                marginTop: (-200 + parseFloat(_this.css(_this.image.$item, 'margin-top'))) + 'px'
            });
        }
    };

    // init video
    var def_initImg = Jarallax.prototype.initImg;
    Jarallax.prototype.initImg = function () {
        var _this = this;
        var defaultResult = def_initImg.apply(_this);

        if(!_this.options.videoSrc) {
            _this.options.videoSrc = _this.$item.getAttribute('data-jarallax-video') || false;
        }

        if(_this.options.videoSrc) {
            var video = new VideoWorker(_this.options.videoSrc, {
                startTime: _this.options.videoStartTime || 0,
                endTime: _this.options.videoEndTime || 0
            });

            if(video.isValid()) {
                _this.image.useImgTag = true;

                video.on('ready', function () {
                    var oldOnScroll = _this.onScroll;
                    _this.onScroll = function () {
                        oldOnScroll.apply(_this);
                        if(_this.isVisible()) {
                            video.play();
                        } else {
                            video.pause();
                        }
                    };
                });

                video.on('started', function () {
                    _this.image.$default_item = _this.image.$item;
                    _this.image.$item = _this.$video;

                    // set video width and height
                    _this.image.width  = _this.options.imgWidth = _this.video.videoWidth || 1280;
                    _this.image.height = _this.options.imgHeight = _this.video.videoHeight || 720;
                    _this.coverImage();
                    _this.clipContainer();
                    _this.onScroll();

                    // hide image
                    if(_this.image.$default_item) {
                        _this.image.$default_item.style.display = 'none';
                    }
                });

                _this.video = video;

                if(video.type !== 'local') {
                    video.getImageURL(function (url) {
                        _this.image.src = url;
                        _this.init();
                    });
                }
            }

            // prevent default image loading when not local video
            if(video.type !== 'local') {
                return false;
            }

            // set empty image on local video if not defined
            else if (!defaultResult) {
                _this.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
                return true;
            }
        }

        return defaultResult;
    };

    // Destroy video parallax
    var def_destroy = Jarallax.prototype.destroy;
    Jarallax.prototype.destroy = function () {
        var _this = this;

        def_destroy.apply(_this);
    };
}());
