/**
 * progressButton.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */
;(function (window) {

    'use strict';

    // https://gist.github.com/edankwan/4389601
    Modernizr.addTest('csstransformspreserve3d', function () {
        var prop = Modernizr.prefixed('transformStyle');
        var val = 'preserve-3d';
        var computedStyle;
        if (!prop) return false;

        prop = prop.replace(/([A-Z])/g, function (str, m1) {
            return '-' + m1.toLowerCase();
        }).replace(/^ms-/, '-ms-');

        Modernizr.testStyles('#modernizr{' + prop + ':' + val + ';}', function (el, rule) {
            computedStyle = window.getComputedStyle ? getComputedStyle(el, null).getPropertyValue(prop) : '';
        });

        return (computedStyle === val);
    });

    function extend(a, b) {
        for (var key in b) {
            if (b.hasOwnProperty(key)) {
                a[key] = b[key];
            }
        }
        return a;
    }

    // support
    var support = {
            transitions: Modernizr.csstransitions,
            transforms3d: Modernizr.csstransforms3d && Modernizr.csstransformspreserve3d
        },
        // transition end event name
        transEndEventNames = {
            'WebkitTransition': 'webkitTransitionEnd',
            'MozTransition': 'transitionend',
            'OTransition': 'oTransitionEnd',
            'msTransition': 'MSTransitionEnd',
            'transition': 'transitionend'
        },
        transEndEventName = transEndEventNames[Modernizr.prefixed('transition')];

    function ProgressButton(el, options) {
        this.button = el;
        this.options = extend({}, this.options);
        extend(this.options, options);
        this._init();
    }

    ProgressButton.prototype.options = {
        // time in ms that the status (success or error will be displayed)
        // during this time the button will be disabled
        statusTime: 1500
    };

    ProgressButton.prototype._init = function () {
        this._validate();
        // create structure
        this._create();
        // init events
        this._initEvents();
    };

    ProgressButton.prototype._validate = function () {
        // we will consider the fill/horizontal as default
        if (this.button.getAttribute('data-style') === null) {
            this.button.setAttribute('data-style', 'fill');
        }
        if (this.button.getAttribute('data-vertical') === null && this.button.getAttribute('data-horizontal') === null) {
            this.button.setAttribute('data-horizontal', '');
        }
        if (!support.transforms3d && this.button.getAttribute('data-perspective') !== null) {
            this.button.removeAttribute('data-perspective');
            this.button.setAttribute('data-style', 'fill');
            this.button.removeAttribute('data-vertical');
            this.button.setAttribute('data-horizontal', '');
        }
    };

    ProgressButton.prototype._create = function () {
        var textEl = document.createElement('span');
        textEl.className = 'content';
        textEl.innerHTML = this.button.innerHTML;
        var progressEl = document.createElement('span');
        progressEl.className = 'progress';

        var progressInnerEl = document.createElement('span');
        progressInnerEl.className = 'progress-inner';
        progressEl.appendChild(progressInnerEl);
        // clear content
        this.button.innerHTML = '';

        if (this.button.getAttribute('data-perspective') !== null) {
            var progressWrapEl = document.createElement('span');
            progressWrapEl.className = 'progress-wrap';
            progressWrapEl.appendChild(textEl);
            progressWrapEl.appendChild(progressEl);
            this.button.appendChild(progressWrapEl);
        } else {
            this.button.appendChild(textEl);
            this.button.appendChild(progressEl);
        }

        // the element that serves as the progress bar
        this.progress = progressInnerEl;

        // property to change on the progress element
        if (this.button.getAttribute('data-horizontal') !== null) {
            this.progressProp = 'width';
        } else if (this.button.getAttribute('data-vertical') !== null) {
            this.progressProp = 'height';
        }
        this._enable();
    };

    ProgressButton.prototype._setProgress = function (val) {
        this.progress.style[this.progressProp] = 100 * val + '%';
    };

    ProgressButton.prototype._initEvents = function () {
        var self = this;
        this.button.addEventListener('click', function () {
            // disable the button
            self.button.setAttribute('disabled', '');
            // add class state-loading to the button (applies a specific transform to the button depending which data-style is defined - defined in the stylesheets)
            classie.remove(self.progress, 'notransition');
            classie.add(this, 'state-loading');

            setTimeout(function () {
                    if (typeof self.options.callback === 'function') {
                        self.options.callback(self);
                    } else {
                        self._setProgress(1);
                        var onEndTransFn = function (ev) {
                            if (support.transitions && ev.propertyName !== self.progressProp) return;
                            this.removeEventListener(transEndEventName, onEndTransFn);
                            self._stop();
                        };

                        if (support.transitions) {
                            self.progress.addEventListener(transEndEventName, onEndTransFn);
                        } else {
                            onEndTransFn.call();
                        }

                    }
                },
                self.button.getAttribute('data-style') === 'fill' ||
                self.button.getAttribute('data-style') === 'top-line' ||
                self.button.getAttribute('data-style') === 'lateral-lines' ? 0 : 200);
        });
    };

    ProgressButton.prototype._stop = function (status) {
        var self = this;

        setTimeout(function () {
            // fade out progress bar
            self.progress.style.opacity = 0;
            var onEndTransFn = function (ev) {
                if (support.transitions && ev.propertyName !== 'opacity') return;
                this.removeEventListener(transEndEventName, onEndTransFn);
                classie.add(self.progress, 'notransition');
                self.progress.style[self.progressProp] = '0%';
                self.progress.style.opacity = 1;
            };

            if (support.transitions) {
                self.progress.addEventListener(transEndEventName, onEndTransFn);
            } else {
                onEndTransFn.call();
            }


            // add class state-success to the button
            if (typeof status === 'number') {
                var statusClass = status >= 0 ? 'done' : 'state-error';
                classie.add(self.button, statusClass);
                // after options.statusTime remove status
                setTimeout(function () {
                    classie.remove(self.button, statusClass);
                    self._enable();
                }, self.options.statusTime);
            } else {
                self._enable();
            }

            // remove class state-loading from the button
            classie.remove(self.button, 'state-loading');
        }, 100);
    };

    // enable button
    ProgressButton.prototype._enable = function () {
        this.button.removeAttribute('disabled');
    };

    // add to global namespace
    window.ProgressButton = ProgressButton;

})(window);