(function( $ ) {

$.widget( "bs.songMetadataForm", {  

    options: {
        // The song object to render.
        song: null, 

        // Selectors
        submit: '.song-save',
        songEditTemplate: '#song-edit-template',
        songEditTemplateName: 'songEdit',
        genreTemplate: '#genre-template',
        genreTemplateName: 'genres',
        songField: '.song-resource',
        imageField: '.image-resource'
    },

    attachedSong: function () {
        return this.attachedSong;
    },

    attachedImage: function () {
        return this.attachedImage;
    },

    attachSong: function (uploadResult) {
        this._songField().val(uploadResult.id);
        this.attachedSong = uploadResult;
        this.validate();
    },

    detachSong: function () {
        this._songField().val('');
        this.attachedSong = null;
        this.validate();
    },

    attachImage: function (uploadResult) {
        this._imageField().val(uploadResult.id);
        this.attachedImage = uploadResult;
        this.validate();
    },

    detachImage: function () {
        this._imageField().val('');
        this.attachedImage = null;
        this.validate();
    },

    submit: function () {
        var self = this;

        function postData() {
            var $form = self.element.find('form'),
                saveUrl = $form.attr('action');

            return $.ajax({
                url: saveUrl,
                type: 'POST',
                data: $form.serialize()
            });
        }

        function onSuccess(result) {
            $.location().update('/account');
        }

        function onError(xhr) {
            switch (xhr.status) {
                case 401:
                    $.user.login().then(function () {
                        self.submit();
                    });
                    break;

                case 403:
                    self._renderSong($.parseJSON(xhr.responseText));
                    break;

                default:
                    throw 'Error posting form.';
            }
        }

        postData().then(onSuccess, onError);
    },

    validate: function () {
        if (this.validationInitialized) {
            this.validator.form();
        }
    },

    _init: function() {
        var self = this,
            song = this.options.song;

        this.validationInitialized = false;

        if (!song) {
            throw 'A song must be passed in to songMetadataForm';
        }

        this._initializeGenres().then(function (genres) {
            self.genres = genres;
            self._renderSong(song);
        });
        this._initializeTemplates();
    },

    _initializeGenres: function () {
        var self = this,
            deferred = new $.Deferred();

        $.getGenreList(this.element.data('genres-href'), function(genres) {
            deferred.resolve(genres);
        });

        return deferred.promise();
    },

    _initializeTemplates: function () {
        $(this.options.songEditTemplate).template(this.options.songEditTemplateName);
        $(this.options.genreTemplate).template(this.options.genreTemplateName);
    },

    _renderSong: function (song) {
        var self = this,
            selectedGenreId = null;

        $.tmpl(this.options.songEditTemplateName, {song: song, genres: self.genres}).appendTo(this.element.empty());

        // Initialize code
        this._initializeValidation();

        if (song.songResource && song.songResource.id) {
            this.attachSong(song.songResource);
        }
        else {
            this.attachedSong = null;
        }

        if (song.imageResource && song.imageResource.id) {
            this.attachImage(song.imageResource);
        }
        else {
            this.attachedImage = null;
        }

        this._initializeSubmitButton();
    },

    _initializeValidation: function () {
        var that = this;


        this.validator = this.element.find('form').validate({ 
            debug: true,
            errorLabelContainer: ".client-errors",
            errorClass: "ui-state-error-text",
            wrapper: "li",

            rules: { 
                "artist.name": { 
                    required: true,
                    maxlength: 50
                }, 
                title: { 
                    required: true, 
                    maxlength: 50
                }, 
                description: {
                    required: false,
                    maxlength: 500,
                },
                "songResource.id": { 
                    required: true, 
                    min: 1 
                }, 
                "imageResource.id": { 
                    required: true, 
                    min: 1 
                } ,
                "genre.id": { 
                    required: true,
                    min: 1
                } 
            }, 

            messages: { 
                "artist.name": { 
                    required: "Enter an artist name.",
                    maxlength: $.format("Artist name can be no more than {0} characters.")
                }, 
                title: { 
                    required: "Enter a title", 
                    maxlength: $.format("Title can be no more than {0} characters.")
                }, 
                description: { 
                    maxlength: $.format("Description can be no more than {0} characters.")
                }, 
                "songResource.id": {
                    required: "Please attach a song.",
                    min: "Please attach a song."
                },
                "imageResource.id": {
                    required: "Please attach an image.",
                    min: "Please attach an image."
                },
                "genre.id": {
                    required: "Please select a genre.",
                    min: "Please select a genre."
                }
            }, 

            submitHandler: function () { 
                that.submit();
                //alert("submitted!"); 
            } 
        }); 

        this.validationInitialized = true;
    },

    _initializeSubmitButton: function () {
        var $form = this.element.find('form');

        $(this.options.submit).button({
        })
        .bind('click', function () {
            $form.submit();
            return false;
        });
    },

    _allFilesAreAttached: function () {
        return this.attachedSong && this.attachedImage;
    },

    destroy: function() {
        $.Widget.prototype.destroy.apply(this);
        this._unbindSubmitHandler();
    },

    _unbindSubmitHandler: function () {
        this.element.find('form').unbind('submit');
    },

    _songField: function () {
        return this.element.find(this.options.songField);
    },

    _imageField: function () {
        return this.element.find(this.options.imageField);
    }
}); 

})( jQuery );

