/*
 * <progress> polyfill
 * Don't forget to also include progress-polyfill.css!
 * @author Lea Verou http://leaverou.me
 */

(function(){

// Test browser support first
    if('position' in document.createElement('progress')) {
        return;
    }

    /**
     * Private functions
     */

// Smoothen out differences between Object.defineProperty
// and __defineGetter__/__defineSetter__
    var defineProperty, supportsEtters = true;

    if(Object.defineProperty) {
        // Changed to fix issue #3 https://github.com/LeaVerou/HTML5-Progress-polyfill/issues/3
        defineProperty = function(o, property, etters) {
            etters.enumerable = true;
            etters.configurable = true;

            try {
                Object.defineProperty(o, property, etters);
            } catch(e) {
                if(e.number === -0x7FF5EC54) {
                    etters.enumerable = false;
                    Object.defineProperty(o, property, etters);
                }
            }
        }
    }
    else {
        if ('__defineSetter__' in document.body) {
            defineProperty = function(o, property, etters) {
                o.__defineGetter__(property, etters.get);

                if(etters.set) {
                    o.__defineSetter__(property, etters.set);
                }
            };
        }
        else {
            // Fallback to regular properties if getters/setters are not supported
            defineProperty = function(o, property, etters) {
                o[property] = etters.get.call(o);
            },
                supportsEtters = false;
        }
    }

    try {
        [].slice.apply(document.images)

        var arr = function(collection) {
            return [].slice.apply(collection);
        }
    } catch(e) {
        var arr = function(collection) {
            var ret = [], len = collection.length;

            for(var i=0; i<len; i++) {
                ret[i] = collection[i];
            }

            return ret;
        }
    }

// Does the browser use attributes as properties? (IE8- bug)
    var attrsAsProps = (function(){
        var e = document.createElement('div');
        e.foo = 'bar';
        return e.getAttribute('foo') === 'bar';
    })();

    var self = window.ProgressPolyfill = {
        DOMInterface: {
            max: {
                get: function(){
                    return parseFloat(this.getAttribute('aria-valuemax')) || 1;
                },

                set: function(value) {
                    this.setAttribute('aria-valuemax', value);

                    if(!attrsAsProps) {
                        this.setAttribute('max', value);
                    }

                    self.redraw(this);
                }
            },

            value: {
                get: function(){
                    return parseFloat(this.getAttribute('aria-valuenow')) || 0;
                },

                set: function(value) {
                    this.setAttribute('aria-valuenow', value);

                    if(!attrsAsProps) {
                        this.setAttribute('value', value);
                    }

                    self.redraw(this);
                }
            },

            position: {
                get: function(){
                    return this.hasAttribute('aria-valuenow')? this.value/this.max : -1;
                }
            },

            labels: {
                get: function(){
                    var label = this.parentNode;

                    while(label && !/^label$/i.test(label.nodeName)) {
                        label = label.parentNode;
                    }

                    var labels = label? [label] : [];

                    if(this.id && document.querySelectorAll) {
                        var forLabels = arr(document.querySelectorAll('label[for="' + this.id + '"]'));

                        if(forLabels.length) {
                            labels = labels.concat(forLabels);
                        }
                    }

                    return labels;
                }
            }
        },

        redraw: function redraw(progress) {
            if(!self.isInited(progress)) {
                self.init(progress);
            }
            else if(!attrsAsProps) {
                progress.setAttribute('aria-valuemax', parseFloat(progress.getAttribute('max')) || 1);

                if(progress.hasAttribute('value')) {
                    progress.setAttribute('aria-valuenow', parseFloat(progress.getAttribute('value')) || 0);
                }
                else {
                    progress.removeAttribute('aria-valuenow');
                }
            }

            if(progress.position !== -1) {
                progress.style.paddingRight = progress.offsetWidth * (1-progress.position) + 'px';
            }
        },

        isInited: function(progress) {
            return progress.getAttribute('role') === 'progressbar';
        },

        init: function (progress) {
            if(self.isInited(progress)) {
                return; // Already init-ed
            }

            // Add ARIA
            progress.setAttribute('role', 'progressbar');
            progress.setAttribute('aria-valuemin', '0');
            progress.setAttribute('aria-valuemax', parseFloat(progress.getAttribute('max')) || 1);

            if(progress.hasAttribute('value')) {
                progress.setAttribute('aria-valuenow', parseFloat(progress.getAttribute('value')) || 0);
            }

            // We can't add them on a prototype, as it's the same for all unknown elements
            for(var attribute in self.DOMInterface) {
                defineProperty(progress, attribute, {
                    get: self.DOMInterface[attribute].get,
                    set: self.DOMInterface[attribute].set
                });
            }

            self.redraw(progress);
        },

        // Live NodeList, will update automatically
        progresses: document.getElementsByTagName('progress')
    };



    for(var i=self.progresses.length-1; i>=0; i--) {
        self.init(self.progresses[i]);
    }

// Take care of future ones too, if supported
    if(document.addEventListener) {
        document.addEventListener('DOMAttrModified', function(evt) {
            var node = evt.target, attribute = evt.attrName;

            if(/^progress$/i.test(node.nodeName) && (attribute === 'max' || attribute === 'value')) {
                self.redraw(node);
            }
        }, false);

        document.addEventListener('DOMNodeInserted', function(evt) {
            var node = evt.target;

            if(/^progress$/i.test(node.nodeName)) {
                self.init(node);
            }
        }, false);
    }

})();