window.ABS = window.ABS || {};
jQuery(function () {
    ABS.Collection = ABS.Collection || {};

    ABS.Collection.TagList = Backbone.Collection.extend({
        model : ABS.Model.Tag,
        url : "/user/tags.json",

        // given a saved tagging add it to this collection
        addTagging : function(tagging) {
            if (this.get(tagging.name)) {
                this.get(tagging.name).get('taggings').push(tagging);
            }
            else {
                this.add({
                    id : tagging.name,
                    taggings : [tagging]
                });
            }
            return this.get(tagging.name);
        },

        // find all tags with references belonging to this chapter
        getByChapter : function(osisId) {
            var chap = ABS.common.osis.getComponents(osisId);
            var tags = {};
            this.each(function(tag) {
                var refs = tag.getReferences();
                _.each(refs, function(ref) {
                    var start = ABS.common.osis.getComponents(ref.start);
                    if (start.book == chap.book && start.chapter == chap.chapter) {
                        if (!(ref.start in tags)) {
                            tags[ref.start] = [];
                        }
                        if (!_.include(tags[ref.start], tag)) {
                            tags[ref.start].push(tag);
                        }
                    }
                });
            });
            return tags;
        }
    });

    ABS.Collection.NoteList = Backbone.Collection.extend({
        model : ABS.Model.Note,
        url : "/user/notes.json",

        // find all tags with references belonging to this chapter
        getByChapter : function(osisId) {
            var chap = ABS.common.osis.getComponents(osisId);
            var notes = {};
            this.each(function(note) {
                note.get('references').each(function(ref) {
                    var start = ABS.common.osis.getComponents(ref.get('start'));
                    if (start.book == chap.book && start.chapter == chap.chapter) {
                        if (!(ref.start in notes)) {
                            notes[ref.get('start')] = [];
                        }
                        notes[ref.get('start')].push(note);
                    }
                });
            });
            return notes;
        }
    });

    ABS.Collection.TaggingList = Backbone.Collection.extend({
        model : ABS.Model.Tagging,
        url : "/user/taggings.json",

        initialize: function() {
        }
    });

    ABS.Collection.ReferenceList = Backbone.Collection.extend({
        model: ABS.Model.Reference
    });

    ABS.Collection.VersionList = Backbone.Collection.extend({
        model: ABS.Model.Version,
        url: "/versions.json",

        initialize: function() {
            this.sortVersions();

            this.bind('refresh', this.sortVersions);
        },

        // Group versions by language
        // and sort both alphabetically
        sortVersions: function() {
            var getLang = function (ver) {
                    return ver.get('lang');
                },
                getLangAndAbbr = function (ver) {
                    return ver.get('lang') + ver.get('display_abbreviation');
                };

            this.sortedByLang = _.groupBy(this.sortBy(getLangAndAbbr), getLang);
        }
    });

    ABS.Collection.UserVersionList = Backbone.Collection.extend({
        model: ABS.Model.Version,
        url: "/user/versions.json",

        initialize: function() {
        },

        // Save the user's My Versions preferences
        // Accepts a function to call with the returned data on
        // success.
        // Fails silently if there's an error communicating
        // with the server.
        save: function(successFunction) {
            var myVersionIDs = this.pluck("id");

            $.post(
                this.url,
                { 'my_versions': myVersionIDs },
                successFunction,
                "json"
            );
        }
    });

    ABS.Collection.SectionList = Backbone.Collection.extend({
        model: ABS.Model.Section
    });

    ABS.Collection.BookList = Backbone.Collection.extend({
        model: ABS.Model.Book,

        initialize: function() {
            this.bind('refresh', function () {
                this.bySection = _.groupBy(this.models, function (book) {
                    return book.get('testament');
                });
            });
        }
        
    });
    ABS.Collection.SearchResultsList = Backbone.Collection.extend({
        model: ABS.Model.SearchResults,

        initialize: function() {
        }
    });
    ABS.Collection.ChapterList = Backbone.Collection.extend({
        model: ABS.Model.Chapter,

        initialize: function () {
            this.trackPrimaryModel();
        },

        // we need to know which chapter model is the primary one
        // for header display and previous / next buttons
        trackPrimaryModel: function() {
            // for refresh just grab the first one
            // the chapters are auto-sorted so this might not be accurate
            this.bind('refresh', function() {
                this.primaryModel = this.at(0);
            });

            this.bind('add', function() {
                if (this.length === 1) {
                    this.primaryModel = this.at(0);
                }
            });
        },

        // this should be the absolute order of the chapter within the version
        comparator: function(chapter) {
            return chapter.get('order');
        },

        // spans are nested arrays of form
        // [ ['Gen.1.1', 'Gen.1.2'] ]
        // first element of inner array is start of span
        // second element of inner array is end of span
        //
        // we want a bunch of human friendly references
        getReferencesFromSpans : function(spans) {
            var that = this;
            var refs = [];
            this.each(function(chapter) {
                var chapterComps = ABS.common.osis.getComponents(chapter.id);
                _.each(spans, function(span) {
                    var startComps = ABS.common.osis.getComponents(span[0]);
                    var endComps   = ABS.common.osis.getComponents(span[1]);

                    if (startComps.book === chapterComps.book && startComps.chapter === chapterComps.chapter) {
                        var ref = chapter.get('display') + ':' + startComps.verse;
                        if (startComps.verse !== endComps.verse) {
                            ref += '-' + endComps.verse;
                        }
                        refs.push(ref);
                    }
                });
            });
            return refs;
        },

        // spans are nested arrays of form
        // [ ['Gen.1.1', 'Gen.1.2'] ]
        // first element of inner array is start of span
        // second element of inner array is end of span
        //
        // we want shortened references for items like twitter where
        // space is at a premium.
        getShortReferencesFromSpans : function(spans) {
            var that = this;
            var refs = [];
            this.each(function(chapter) {
                var chapterComps = ABS.common.osis.getComponents(chapter.id);
                _.each(spans, function(span) {
                    var startComps = ABS.common.osis.getComponents(span[0]);
                    var endComps   = ABS.common.osis.getComponents(span[1]);

                    if (startComps.book === chapterComps.book && startComps.chapter === chapterComps.chapter) {
                        var ref = startComps.book + ' ' + startComps.chapter + ':' + startComps.verse;
                        if (startComps.verse !== endComps.verse) {
                            ref += '-' + endComps.verse;
                        }
                        refs.push(ref);
                    }
                });
            });
            return refs;
        },


        // given an array of chapters, add them to this collection
        // iff they are expected on either end of the collection.
        // an array is expected as the parameter, not a collection,
        // because in some instances the order of chapters is important
        // and we don't want to use the ordering enforced by the collection
        addConsecutive: function(chapters) {
            var that = this;
            // remove any non-chapters
            chapters = _.filter(chapters, function(chap) {
                return chap.id;
            });
            // if it is empty add all the chapters (assume they are consecutive)
            if (this.length === 0) {
                that.add(chapters);
            }
            else {
                // find out which ones are consecutive with current list
                do {
                    var matchFound = false;
                    _.each(chapters, function(chapter) {
                        if (that.first().get('prevChapterId') === chapter.id ||
                            that.last().get('nextChapterId') === chapter.id) {
                            that.add(chapter);
                            matchFound = true;
                        }
                    });
                } while(matchFound);
            }
        }
    });
    
    ABS.Collection.VerseList = Backbone.Collection.extend({
        model: ABS.Model.Verse
    });

    ABS.Collection.RelevancyVoteList = Backbone.Collection.extend({
        model: ABS.Model.RelevancyVote
    });
    
    // A collection of available developer tools
    ABS.Collection.DeveloperTools = Backbone.Collection.extend(
        
        // instance attributes
        {
            model: ABS.Model.DeveloperTool,
            
            initialize: function () {
                this.add(ABS.Collection.DeveloperTools.types);
            }
        },
        
        // class attributes
        {
            types: [
                {id: 'widget', name: 'Widget', path: '/share/widget' },
                {id: 'highlighter', name: 'Highlighter (Beta)', path: '/pages/highlighter' },
                {id: 'api', name: 'API', path: '/pages/api' }
            ]
        }
    );

});



