'use strict';

/*
* Qusion UI Combo 1.0
*
* Copyright 2011, AUTHORS.txt (http://qusion.net/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://qusion.net/license
*
* http://docs.qusion.net/ui/upload
*
* Depends:
*	jquery.ui.widget.js
*	jquery.fileupload.js
*	jquery.iframe-transport.js
*/

(function() {

    $.widget("qusion.upload", {
        options: {
            extensions: [],
            multiple: true,
            findForm: true
        },
        _create: function() {
            var self = this, element = this.element, options = this.options;
            self.files = [];

            self.table = $("<div><table><tbody></tbody></table></div>")
                .addClass("q-upload")
                .insertAfter(element);

            self.form = $(element.parents('form'));

            self.api = element.fileupload({
                singleFileUploads: true,
                multiple:false,
                add: function(e, data) {
                    self._add(data.files[0]);
                },
                progress: function(e, data) {
                    self._progress(data.files[0], data);
                },
                done: function (e, data) {
                    self._done(data.files[0], data);

                },
                formData: function() {
                    if (self.form && options.findForm === true)
                        return self.form.serializeArray();
                }
            }).data("blueimp-fileupload");

        },
        send: function() {
            var self = this, element = this.element, options = self.options;
            var waiting = $.grep(self.files, function(f) {
                return f.done === false;
            });

            waiting = $.map(waiting, function(f) {
                f.uploading = true;
                return f.file;
            });

            $.each(waiting, function(i, w) {
                self._reset(w.name);

                self.api.send({ files: w })
                    .error(function (jqXHR, textStatus, errorThrown) {
                        console.log(jqXHR);
                        self._error(w, { jqXHR: jqXHR, textStatus: textStatus, errorThrown: errorThrown });
                    });
            });
        },
        clear: function() {
            this.files = [];
            this.table.find('tbody').empty();
        },
        waiting: function() {
            var self = this, element = this.element;
            var waiting = $.grep(self.files, function(f) {
                return f.done === false && !f.uploading;
            });
            return waiting;
        },
        validate: function(file) {
            var self = this, options = self.options;
            // validate extensions
            var extension = file.name.substring(file.name.lastIndexOf('.') + 1);
            var pattern = options.extensions.join('|');
            var reg = new RegExp(pattern);
            return reg.test(extension.toLowerCase());
        },
        _reset: function(name) {
            var self = this;
            self._container(name)
                .removeClass('upload-error')
                .find('.progress .bar').css({ width: '0%' });
        },
        _container: function(name) {
            return this.table.find('[data-key="' + name + '"]');
        },
        _error: function(file, data) {
            var self = this;
           
            var index = self._find(file.name);
            self.files[index].error = true;
            self._container(file.name).addClass('upload-error');
            self._container(file.name).find('td.file-error').text(data.jqXHR.responseJSON.MaxSize);

            self._trigger("failedUpload", null, data.jqXHR.responseJSON);
        },
        _progress: function(file, data) {
            var self = this;
            var progress = parseInt(data.loaded / data.total * 100, 10);
            self._container(file.name).find('.progress .bar').css({ width: progress + '%' });
        },
        _done: function(file, data) {
            var self = this;
            self._container(file.name).addClass('upload-success');
            var index = self._find(file.name);
            var f = self.files[index];
            f.done = true;
            f.error = false;

            self._trigger("done", null, data);
            
            if(self.waiting().length == 0)
                self._trigger("doneall", null, data);
        },
        _find: function(name) {
            var self = this;

            for (var i = 0; i < self.files.length; i++) {
                var file = self.files[i];
                if (file.name.toLowerCase() == name.toLowerCase())
                    return i;
            }

            return -1;
        },
        _add: function(f) {
            var self = this;
            if (!self.validate(f)) return false;
            var existing = self._find(f.name);
            if (existing == -1) {
                var file = $.extend({ }, { done: false }, { file: f }, f);

                if (self.options.multiple === false && self.files.length >= 1) {
                    self._remove(self.files[0]);
                }

                self.files.push(file);

                var tr = $("<tr />")
                    .attr('data-key', file.name)
                    .data("file", file)
                    .appendTo(self.table.find('tbody'));

                $('<td />', { text: file.name })
                    .addClass('file-name')
                    .appendTo(tr);
                
                $('<td />', { text: "" })
                    .addClass('file-error')
                    .appendTo(tr);

                $('<td />', { text: self._humanFileSize(file.size, true) })
                    .addClass('file-size')
                    .appendTo(tr);

                $('<td />')
                    .addClass('file-progress')
                    .append($('<div />').addClass('progress').append('<div class="bar" />'))
                    .appendTo(tr);

                $('<td />', { html: '<i class="icon-remove" />' })
                    .addClass('file-remove')
                    .click(function() {
                        var file = $(this).parent('tr').data('file');
                        self._remove(file);
                    })
                    .appendTo(tr);
            }
            return true;
        },
        _remove: function(file) {
            var self = this;
            if (!file) return;
            var index = self._find(file.name);
            self.files.splice(index, 1);
            self._container(file.name).remove();

            //console.log(self.files);
        },
        _humanFileSize: function(bytes, si) {
            var thresh = si ? 1000 : 1024;
            if (bytes < thresh) return bytes + ' B';
            var units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
            var u = -1;
            do {
                bytes /= thresh;
                ++u;
            } while (bytes >= thresh);
            return bytes.toFixed(1) + ' ' + units[u];
        }
    });

})(jQuery);