(function ($) {
$.widget( "ui.songManager", {  

    options: {
        // The url of the content html fragment
        url: null,

        // The url parameters of the address
        params: null,

        defaultUrl: '/songs/likedJson',
        deepLinkPath: 'likedSongs',
        managerName: 'likedSongsManager',

        // Selectors
        songArray: '#songs',
        pager: '#recipe-pager',
        filter: '#recipe-filter',
        player: '#player',                    
        nowPlaying: '#now-playing',
        songTemplate: '#song-template',
        contextBuilder: function (params) {
            var context = {};
            if( params[ 'ordering' ] && params[ 'ordering' ] !== 'NEWEST' ) {
                context[ 'ordering' ] = params[ 'ordering' ];
            }

            if( params[ 'location' ] ) {
                context[ 'location' ] = params[ 'location' ];
            }
            else if( params[ 'startAt' ] ) {
                context[ 'startAt' ] = params[ 'startAt' ];
            }
            else if( params[ 'endBefore' ] ) {
                context[ 'endBefore' ] = params[ 'endBefore' ];
            }

            return context;
        }
    },

    _init: function() {
        var self = this,
            loadPage,
            onLoad;

        if( !this.options.params ) {
            throw "The song manager must be initialized with a set of parameters.";
        }

        if( !this.options.url ) {
            throw "The song manager must be initialized with a url.";
        }

        loadPage = function () {
            self.element.empty().load( self.options.url, onLoad );
        };

        onLoad = function (responseText, textStatus, xhr) {
            switch (xhr.status) {
                case 401:
                    $( '#page' ).loginManager( 'login' ).then( loadPage );
                    break;

                default:
                    $( self.options.pager ).pager({
                        $songArray: $( self.options.songArray )
                    });

                    self.element.delegate( '#songs .haudio', 'click', function( event ) {
                        var item = $.tmplItem( this ).data;

                        $( self.options.player ).player( 'playRecipeItem', item );
                    });

                    $( self.options.filter ).songFilter();

                    $( self.options.songArray ).songArray({
                        template: $( self.options.songTemplate ),
                        defaultUrl: self.options.defaultUrl,
                        deepLinkPath: self.options.deepLinkPath,
                        managerName: self.options.managerName
                    });

                    self.currentContext = self._buildContext( self.options.params );
                    self.element.trigger( 'update.recipeManager', [ self.currentContext ] );
            }
        };

        loadPage();

        function contextsAreEqual( ctx1, ctx2 ) {
            var isEqual = true;

            if( ctx1 === ctx2 ) {
                return true;
            }

            if( !$.isPlainObject( ctx1 ) || !$.isPlainObject( ctx2 ) ) {
                return false;
            }


            $.each( ctx1, function( key, value ) {
                if( ctx2[ key ] !== value ) {
                    isEqual = false;
                    return false; // just returns from $.each
                }
            });

            if( !isEqual ) {
                return false;
            }

            $.each( ctx2, function( key, value ) {
                if( ctx1[ key ] !== value ) {
                    isEqual = false;
                    return false; // just returns from $.each
                }
            });

            return isEqual;
        } 


        this.element.bind( 'pageUpdate', function( e, params ) {
            var context = self._buildContext( params );

            if( !contextsAreEqual( self.currentContext, context ) ) {
                self.currentContext = context;
                self.element.trigger( 'update.recipeManager', [ self.currentContext ] );
            }

        });
    },

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

        this.element.unbind( 'pageUpdate' )
                .unbind( 'update.recipeManager' )
                .undelegate( '#songs .haudio', 'click' )
                .empty();
    },

    // This is used by page to send page changes down.
    changeLocation: function( params ) {
        $.location()
            .current()
            .params(this._buildContext(params))
            .update();
    },

    _buildContext: function(params) {
        return this.options.contextBuilder(params);
    }

}); 

})(jQuery);

