/*! UIkit 2.27.2 | www.getuikit.com | © 2014 YOOtheme | MIT License */ (function(addon) {

var component;

if (window.UIkit) {
    component = addon(UIkit);
}

if (typeof define == 'function' && define.amd) {
    define('uikit-parallax', ['uikit'], function(){
        return component || addon(UIkit);
    });
}

})(function(UI){

"use strict";

var parallaxes      = [],
    supports3d      = false,
    scrolltop       = 0,
    wh              = window.innerHeight,
    checkParallaxes = function() {

        scrolltop = UI.$win.scrollTop();

        window.requestAnimationFrame(function(){
            for (var i=0; i < parallaxes.length; i++) {
                parallaxes[i].process();
            }
        });
    };

UI.component('parallax', {

    defaults: {
        velocity : 0.5,
        target   : false,
        viewport : false,
        media    : false
    },

    boot: function() {

        supports3d = (function(){

            var el = document.createElement('div'),
                has3d,
                transforms = {
                    'WebkitTransform':'-webkit-transform',
                    'MSTransform':'-ms-transform',
                    'MozTransform':'-moz-transform',
                    'Transform':'transform'
                };

            // Add it to the body to get the computed style.
            document.body.insertBefore(el, null);

            for (var t in transforms) {
                if (el.style[t] !== undefined) {
                    el.style[t] = 'translate3d(1px,1px,1px)';
                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
                }
            }

            document.body.removeChild(el);

            return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
        })();

        // listen to scroll and resize
        UI.$doc.on('scrolling.uk.document', checkParallaxes);
        UI.$win.on('load resize orientationchange', UI.Utils.debounce(function(){
            wh = window.innerHeight;
            checkParallaxes();
        }, 50));

        // init code
        UI.ready(function(context) {

            UI.$('[data-uk-parallax]', context).each(function() {

                var parallax = UI.$(this);

                if (!parallax.data('parallax')) {
                    UI.parallax(parallax, UI.Utils.options(parallax.attr('data-uk-parallax')));
                }
            });
        });
    },

    init: function() {

        this.base     = this.options.target ? UI.$(this.options.target) : this.element;
        this.props    = {};
        this.velocity = (this.options.velocity || 1);

        var reserved  = ['target','velocity','viewport','plugins','media'];

        Object.keys(this.options).forEach(function(prop){

            if (reserved.indexOf(prop) !== -1) {
                return;
            }

            var start, end, dir, diff, startend = String(this.options[prop]).split(',');

            if (prop.match(/color/i)) {
                start = startend[1] ? startend[0] : this._getStartValue(prop),
                end   = startend[1] ? startend[1] : startend[0];

                if (!start) {
                    start = 'rgba(255,255,255,0)';
                }

            } else {
                start = parseFloat(startend[1] ? startend[0] : this._getStartValue(prop)),
                end   = parseFloat(startend[1] ? startend[1] : startend[0]);
                diff  = (start < end ? (end-start):(start-end));
                dir   = (start < end ? 1:-1);
            }

            this.props[prop] = { start: start, end: end, dir: dir, diff: diff };

        }.bind(this));

        parallaxes.push(this);
    },

    process: function() {

        if (this.options.media) {

            switch(typeof(this.options.media)) {
                case 'number':
                    if (window.innerWidth < this.options.media) {
                        return false;
                    }
                    break;
                case 'string':
                    if (window.matchMedia && !window.matchMedia(this.options.media).matches) {
                        return false;
                    }
                    break;
            }
        }

        var percent = this.percentageInViewport();

        if (this.options.viewport !== false) {
            percent = (this.options.viewport === 0) ? 1 : percent / this.options.viewport;
        }

        this.update(percent);
    },

    percentageInViewport: function() {

        var top     = this.base.offset().top,
            height  = this.base.outerHeight(),
            distance, percentage, percent;

        if (top > (scrolltop + wh)) {
            percent = 0;
        } else if ((top + height) < scrolltop) {
            percent = 1;
        } else {

            if ((top + height) < wh) {

                percent = (scrolltop < wh ? scrolltop : scrolltop - wh) / (top+height);

            } else {

                distance   = (scrolltop + wh) - top;
                percentage = Math.round(distance / ((wh + height) / 100));
                percent    = percentage/100;
            }
        }

        return percent;
    },

    update: function(percent) {

        var $this      = this,
            css        = {transform:'', filter:''},
            compercent = percent * (1 - (this.velocity - (this.velocity * percent))),
            opts, val;

        if (compercent < 0) compercent = 0;
        if (compercent > 1) compercent = 1;

        if (this._percent !== undefined && this._percent == compercent) {
            return;
        }

        Object.keys(this.props).forEach(function(prop) {

            opts = this.props[prop];

            if (percent === 0) {
                val = opts.start;
            } else if(percent === 1) {
                val = opts.end;
            } else if(opts.diff !== undefined) {
                val = opts.start + (opts.diff * compercent * opts.dir);
            }

            if ((prop == 'bg' || prop == 'bgp') && !this._bgcover) {
                this._bgcover = initBgImageParallax(this, prop, opts);
            }

            switch(prop) {

                // transforms
                case 'x':
                    css.transform += supports3d ? ' translate3d('+val+'px, 0, 0)':' translateX('+val+'px)';
                    break;
                case 'xp':
                    css.transform += supports3d ? ' translate3d('+val+'%, 0, 0)':' translateX('+val+'%)';
                    break;
                case 'y':
                    css.transform += supports3d ? ' translate3d(0, '+val+'px, 0)':' translateY('+val+'px)';
                    break;
                case 'yp':
                    css.transform += supports3d ? ' translate3d(0, '+val+'%, 0)':' translateY('+val+'%)';
                    break;
                case 'rotate':
                    css.transform += ' rotate('+val+'deg)';
                    break;
                case 'scale':
                    css.transform += ' scale('+val+')';
                    break;

                // bg image
                case 'bg':

                    // don't move if image height is too small
                    // if ($this.element.data('bgsize') && ($this.element.data('bgsize').h + val - window.innerHeight) < 0) {
                    //     break;
                    // }

                    css['background-position'] = '50% '+val+'px';
                    break;
                case 'bgp':
                    css['background-position'] = '50% '+val+'%';
                    break;

                // color
                case 'color':
                case 'background-color':
                case 'border-color':
                    css[prop] = calcColor(opts.start, opts.end, compercent);
                    break;

                // CSS Filter
                case 'blur':
                    css.filter += ' blur('+val+'px)';
                    break;
                case 'hue':
                    css.filter += ' hue-rotate('+val+'deg)';
                    break;
                case 'grayscale':
                    css.filter += ' grayscale('+val+'%)';
                    break;
                case 'invert':
                    css.filter += ' invert('+val+'%)';
                    break;
                case 'fopacity':
                    css.filter += ' opacity('+val+'%)';
                    break;
                case 'saturate':
                    css.filter += ' saturate('+val+'%)';
                    break;
                case 'sepia':
                    css.filter += ' sepia('+val+'%)';
                    break;

                default:
                    css[prop] = val;
                    break;
            }

        }.bind(this));

        if (css.filter) {
            css['-webkit-filter'] = css.filter;
        }

        this.element.css(css);

        this._percent = compercent;
    },

    _getStartValue: function(prop) {

        var value = 0;

        switch(prop) {
            case 'scale':
                value = 1;
                break;
            default:
                value = this.element.css(prop);
        }

        return (value || 0);
    }

});

// helper

function initBgImageParallax(obj, prop, opts) {

    var img = new Image(), url, element, size, check, ratio, width, height;

    element = obj.element.css({backgroundSize: 'cover',  backgroundRepeat: 'no-repeat'});
    url     = element.css('background-image').replace(/^url\(/g, '').replace(/\)$/g, '').replace(/("|')/g, '');
    check   = function() {

        var w = element.innerWidth(), h = element.innerHeight(), extra = (prop=='bg') ? opts.diff : (opts.diff/100) * h;

        h += extra;
        w += Math.ceil(extra * ratio);

        if (w-extra < size.w && h < size.h) {
            return obj.element.css({backgroundSize: 'auto'});
        }

        // if element height < parent height (gap underneath)
        if ((w / ratio) < h) {

            width  = Math.ceil(h * ratio);
            height = h;

            if (h > window.innerHeight) {
                width  = width * 1.2;
                height = height * 1.2;
            }

        // element width < parent width (gap to right)
        } else {

            width  = w;
            height = Math.ceil(w / ratio);
        }

        element.css({backgroundSize: (width+'px '+height+'px')}).data('bgsize', {w:width,h:height});
    };

    img.onerror = function(){
        // image url doesn't exist
    };

    img.onload = function(){
        size  = {w:img.width, h:img.height};
        ratio = img.width / img.height;

        UI.$win.on('load resize orientationchange', UI.Utils.debounce(function(){
            check();
        }, 50));

        check();
    };

    img.src = url;

    return true;
}

// Some named colors to work with, added by Bradley Ayers
// From Interface by Stefan Petre
// http://interface.eyecon.ro/
var colors = {
    'black': [0,0,0,1],
    'blue': [0,0,255,1],
    'brown': [165,42,42,1],
    'cyan': [0,255,255,1],
    'fuchsia': [255,0,255,1],
    'gold': [255,215,0,1],
    'green': [0,128,0,1],
    'indigo': [75,0,130,1],
    'khaki': [240,230,140,1],
    'lime': [0,255,0,1],
    'magenta': [255,0,255,1],
    'maroon': [128,0,0,1],
    'navy': [0,0,128,1],
    'olive': [128,128,0,1],
    'orange': [255,165,0,1],
    'pink': [255,192,203,1],
    'purple': [128,0,128,1],
    'violet': [128,0,128,1],
    'red': [255,0,0,1],
    'silver': [192,192,192,1],
    'white': [255,255,255,1],
    'yellow': [255,255,0,1],
    'transparent': [255,255,255,0]
};

function calcColor(start, end, pos) {

    start = parseColor(start);
    end   = parseColor(end);
    pos   = pos || 0;

    return calculateColor(start, end, pos);
}

/**!
 * @preserve Color animation 1.6.0
 * http://www.bitstorm.org/jquery/color-animation/
 * Copyright 2011, 2013 Edwin Martin <edwin@bitstorm.org>
 * Released under the MIT and GPL licenses.
 */

// Calculate an in-between color. Returns "#aabbcc"-like string.
function calculateColor(begin, end, pos) {
    var color = 'rgba('
            + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','
            + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','
            + parseInt((begin[2] + pos * (end[2] - begin[2])), 10) + ','
            + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);

    color += ')';
    return color;
}

// Parse an CSS-syntax color. Outputs an array [r, g, b]
function parseColor(color) {

    var match, quadruplet;

    // Match #aabbcc
    if (match = /#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/.exec(color)) {
        quadruplet = [parseInt(match[1], 16), parseInt(match[2], 16), parseInt(match[3], 16), 1];

        // Match #abc
    } else if (match = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/.exec(color)) {
        quadruplet = [parseInt(match[1], 16) * 17, parseInt(match[2], 16) * 17, parseInt(match[3], 16) * 17, 1];

        // Match rgb(n, n, n)
    } else if (match = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
        quadruplet = [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), 1];

    } else if (match = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9\.]*)\s*\)/.exec(color)) {
        quadruplet = [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10),parseFloat(match[4])];

        // No browser returns rgb(n%, n%, n%), so little reason to support this format.
    } else {
        quadruplet = colors[color] || [255,255,255,0];
    }
    return quadruplet;
}

return UI.parallax;

});