/*!
 * Elevator.js
 *
 * MIT licensed
 * Copyright (C) 2015 Tim Holman, http://tholman.com
 */

/*********************************************
 * Elevator.js
 *********************************************/

var Elevator = function(options) {

    'use strict';

    // Elements
    var body = null;

    // Scroll vars
    var animation = null;
    var duration = null; // ms
    var customDuration = false;
    var startTime = null;
    var startPosition = null;
    var endPosition = 0;
    var elevating = false;

    var mainAudio;
    var endAudio;

    var that = this;
    
    /**
     * Utils
     */

    // Thanks Mr Penner - http://robertpenner.com/easing/
    function easeInOutQuad( t, b, c, d ) {
        t /= d / 2;
        if ( t < 1 ) return c / 2 * t * t + b;
        t--;
        return -c / 2 * ( t * ( t -2 ) - 1 ) + b;
    }

    function extendParameters(options, defaults){
        for( var option in defaults ){
            var t = options[option] === undefined && typeof option !== "function";
            if(t){
                options[option] = defaults[option];
            }
        }
        return options;
    }

    function getVerticalOffset(element) {
        var verticalOffset = 0;
        while( element ){
            verticalOffset += element.offsetTop || 0;
            element = element.offsetParent;
        }
        return verticalOffset;
    }

    /**
     * Main
     */

    // Time is passed through requestAnimationFrame, what a world!
    function animateLoop( time ) {
        if ( !startTime ) {
            startTime = time;
        }

        var timeSoFar = time - startTime;
        var easedPosition = easeInOutQuad(timeSoFar, startPosition, endPosition - startPosition, duration);

        window.scrollTo(0, easedPosition);

        if( timeSoFar < duration ) {
            animation = requestAnimationFrame(animateLoop);
        } else {
            animationFinished();
        }
     }

//            ELEVATE!
//              /
//         ____
//       .'    '=====<0
//       |======|
//       |======|
//       [IIIIII[\--()
//       |_______|
//       C O O O D
//      C O  O  O D
//     C  O  O  O  D
//     C__O__O__O__D
//    [_____________]
    this.elevate = function() {

        if( elevating ) {
            return;
        }

        elevating = true;
        startPosition = (document.documentElement.scrollTop || body.scrollTop);

        // No custom duration set, so we travel at pixels per millisecond. (0.75px per ms)
        if( !customDuration ) {
            duration = (startPosition * 1.5);
        }

        requestAnimationFrame( animateLoop );

        // Start music!
        if( mainAudio ) {
            mainAudio.play();
        }
    };

    function browserMeetsRequirements() {
        return window.requestAnimationFrame && window.Audio && window.addEventListener;
    }

    function resetPositions() {
        startTime = null;
        startPosition = null;
        elevating = false;
    }

    function animationFinished() {

        resetPositions();

        // Stop music!
        if( mainAudio ) {
            mainAudio.pause();
            mainAudio.currentTime = 0;
        }

        if( endAudio ) {
            endAudio.play();
        }
    }

    function onWindowBlur() {

        // If animating, go straight to the top. And play no more music.
        if( elevating ) {

            cancelAnimationFrame( animation );
            resetPositions();

            if( mainAudio ) {
                mainAudio.pause();
                mainAudio.currentTime = 0;
            }

            window.scrollTo(0, endPosition);
        }
    }

    function bindElevateToElement( element ) {
        if( element.addEventListener ) {
            element.addEventListener('click', that.elevate, false);
        } else {
            // Older browsers
            element.attachEvent('onclick', function() {
                document.documentElement.scrollTop = endPosition;
                document.body.scrollTop = endPosition;
                window.scroll(0, endPosition);
            });
        }
    }

    function init( _options ) {
        // Bind to element click event, if need be.
        body = document.body;

        var defaults = {
            duration: undefined,
            mainAudio: false,
            endAudio: false,
            preloadAudio: true,
            loopAudio: true,
        };

        _options = extendParameters(_options, defaults);

        if( _options.element ) {
            bindElevateToElement( _options.element );
        }

        // Take the stairs instead
        if( !browserMeetsRequirements() ) {
            return;
        }

        if( _options.duration ) {
            customDuration = true;
            duration = _options.duration;
        }

        if( _options.targetElement ) {
            endPosition = getVerticalOffset(_options.targetElement);
        }

        window.addEventListener('blur', onWindowBlur, false);

        if( _options.mainAudio ) {
            mainAudio = new Audio( _options.mainAudio );
            mainAudio.setAttribute( 'preload', _options.preloadAudio );
            mainAudio.setAttribute( 'loop', _options.loopAudio );
        }

        if( _options.endAudio ) {
            endAudio = new Audio( _options.endAudio );
            endAudio.setAttribute( 'preload', 'true' );
        }
    }

    init(options);
};
