define(["js/views/baseview", "underscore", "jquery", "jquery.form"],
function(BaseView, _, $) {
var UploadDialog = BaseView.extend({
    options: {
        shown: true,
        successMessageTimeout: 2000 // 2 seconds
    },
    initialize: function() {
        this.template = _.template($("#upload-dialog-tpl").text());
        this.listenTo(this.model, "change", this.render);
    },
    render: function() {
        var isValid = this.model.isValid();
        var selectedFile = this.model.get('selectedFile');
        var oldInput = this.$("input[type=file]").get(0);
        this.$el.html(this.template({
            shown: this.options.shown,
            url: CMS.URL.UPLOAD_ASSET,
            title: this.model.escape('title'),
            message: this.model.escape('message'),
            selectedFile: selectedFile,
            uploading: this.model.get('uploading'),
            uploadedBytes: this.model.get('uploadedBytes'),
            totalBytes: this.model.get('totalBytes'),
            finished: this.model.get('finished'),
            error: this.model.validationError
        }));
        // Ideally, we'd like to tell the browser to pre-populate the
        // <input type="file"> with the selectedFile if we have one -- but
        // browser security prohibits that. So instead, we'll swap out the
        // new input (that has no file selected) with the old input (that
        // already has the selectedFile selected). However, we only want to do
        // this if the selected file is valid: if it isn't, we want to render
        // a blank input to prompt the user to upload a different (valid) file.
        if (selectedFile && isValid) {
            $(oldInput).removeClass("error");
            this.$('input[type=file]').replaceWith(oldInput);
        }
        return this;
    },
    events: {
        "change input[type=file]": "selectFile",
        "click .action-cancel": "hideAndRemove",
        "click .action-upload": "upload"
    },
    selectFile: function(e) {
        this.model.set({
            selectedFile: e.target.files[0] || null
        });
    },
    show: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.options.shown = true;
        $("body").addClass('dialog-is-shown');
        return this.render();
    },
    hide: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.options.shown = false;
        $("body").removeClass('dialog-is-shown');
        return this.render();
    },
    hideAndRemove: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        return this.hide().remove();
    },
    upload: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.set('uploading', true);
        this.$("form").ajaxSubmit({
            success: _.bind(this.success, this),
            error: _.bind(this.error, this),
            uploadProgress: _.bind(this.progress, this),
            data: {
                // don't show the generic error notification; we're in a modal,
                // and we're better off modifying it instead.
                notifyOnError: false
            }
        });
    },
    progress: function(event, position, total, percentComplete) {
        this.model.set({
            "uploadedBytes": position,
            "totalBytes": total
        });
    },
    success: function(response, statusText, xhr, form) {
        this.model.set({
            uploading: false,
            finished: true
        });
        if(this.options.onSuccess) {
            this.options.onSuccess(response, statusText, xhr, form);
        }
        var that = this;
        this.removalTimeout = setTimeout(function() {
            that.hide().remove();
        }, this.options.successMessageTimeout);
    },
    error: function() {
        this.model.set({
            "uploading": false,
            "uploadedBytes": 0,
            "title": gettext("We're sorry, there was an error")
        });
    }
});
return UploadDialog;
}); // end define()
