var BS = BS || {};

BS.namespace = function (ns) {
    var parts = ns.split('.'),
        root = 'BS';

    function nextContext(ctx, part) {
        if (_.isUndefined(ctx[part])) {
            ctx[part] = {};
        }

        return ctx[part];
    }

    if (_.first(parts) === root) {
        parts = _.rest(parts);
    }

    return _.inject(parts, nextContext, BS);
};


(function (app, $, _) {

    var root = this;

    var PAGE_LINK_NAMES = ['self', 'first', 'last', 'prev', 'next'];

    var List = Backbone.Collection.extend({
        model: ListItem,

        initialize: function (models, options) {
            var self = this;

            this.selfUrl = options.url;
        },

        parse: function (response) {
            var self = this;

            self.links = app.util.clone(response.links, {keys: PAGE_LINK_NAMES});

            return _.map(response.data, function (itemData) {
                return {
                    item: itemData,
                    list: self
                };
            });
        },

        url: function () {
            return this.selfUrl;
        },

        hasPrevious: function () {
            return this.links.prev ? true : false;
        },

        hasNext: function () {
            return this.links.next ? true : false;
        },

        previous: function () {
        },

        next: function () {
        }
    });

    var ListItem = Backbone.Model.extend({
        initialize: function (attributes, options) {
            var self = this,
                wrappedModel = this.itemBuilder(attributes.item);

            function handleModelDestroy(model, collection, options) {
                self.destroy();
            }

            this.item = wrappedModel;

            wrappedModel.bind('destroy', handleModelDestroy, this);
        },

        url: null,

        itemBuilder: function (attributes) {
            throw 'You must provide an implementation of itemBuilder';
        },

        destroy: function (options) {
            var returnValue;
            options || (options = {});

            returnValue = this.trigger('destroy', this, this.collection, options);
            this.clear({silent: true});
            this.item = null;
            this.unbind();

            return returnValue;
        }

    });

    var Song = Backbone.Model.extend({
        initialize: function (attributes, options) {
            this.links = _.clone(attributes.links);
        },

        url: function () {
            return this.links.self;
        },

        destroy: function (options) {
            var songOptions = _.extend({}, options, {
                url: this.links['delete']
            });

            return Backbone.Model.prototype.destroy.apply(this, [songOptions]);
        }
    });

    var SongList = List.extend({
        model: ListItem.extend({
            itemBuilder: function (attributes, options) {
                return new Song(attributes);
            }
        })
    });

    var ListItemView = Backbone.View.extend({
        
        initialize: function (options) {
            var self = this;

            this.container = options.container;
            this.isRendered = false;

            this.model.bind('destroy', function (model, collection, options) {
                self.remove();
            });
        },

        render: function () {
            var $content = $.tmpl(this.templateName, this.model.item.attributes);

            if (this.isRendered) {
                $(this.el).replaceWith($content);
            }
            else {
                $content.appendTo(this.container);
                this.isRendered = true;
            }

            this.el = $content.get(0);
            this.delegateEvents();

            return this;
        }
    });

    var ListView = Backbone.View.extend({

        templateName: null,
        itemContainerSelector: 'ul',
        ItemView: ListItemView,
        
        initialize: function (options) {
            this.itemViews = [];
        },

        buildItemView: function (item) {
            return new this.ItemView({
                model: item,
                container: this.itemContainer
            });
        },

        render: function () {
            var self = this,
                items = this.model.toArray(),
                $el = $(this.el);

            $.tmpl(this.templateName).appendTo($el.empty());
            this.itemContainer = $el.find(this.itemContainerSelector).get(0);

            this.itemViews = _.map(items, function (item) {
                return self.buildItemView(item); 
            });

            _.each(this.itemViews, function (view) {view.render()});

            return this;
        }
    });

    var _followDeepLink = function (event) {
        var deepLink = $(event.currentTarget).attr('href');

        event.preventDefault();
        $.location().update(deepLink);
    };

    var AccountSongListView = ListView.extend({
        templateName: 'accountSongList',

        render: function () {
            var self = this;

            ListView.prototype.render.apply(this);

            this.$('.delete-panel').dialog({
                modal: true,
                autoOpen: false
            });

            return this;
        },

        ItemView: ListView.prototype.ItemView.extend({
            templateName: 'songListItem',

            events: {
                'click .deep-link': 'followDeepLink',
                'click .delete': 'verifyAndDelete'
            },

            followDeepLink: function (event) {
                _followDeepLink(event);
            },

            verifyAndDelete: function (event) {
                var self = this,
                    $deletePanel = $('.delete-panel');

                function continueWithDelete() {
                    $deletePanel.dialog('close');
                    self.model.item.destroy();
                }

                function cancelDelete() {
                    $deletePanel.dialog('close');
                }

                event.preventDefault();
                $deletePanel
                    .dialog('option', 'buttons', {
                        "Yep, do it": continueWithDelete,
                        "No way": cancelDelete
                    })
                    .dialog('open');
            }
        })
    });

    Backbone.emulateHTTP = true;

    app.namespace('domain').SongList = SongList;
    app.namespace('view').AccountSongListView = AccountSongListView;
    app.namespace('util').clone = function (obj, options) {
        var result = {};

        _.each(options.keys, function (key) {
            result[key] = obj[key];
        });

        return result;
    };

}).apply(this, [BS, jQuery, _]);


