var moduleName = 'commentsModule';
var module;

try {
    module = angular.module(moduleName);
} catch(err) {
    // named module does not exist, so create one
    module = angular.module(moduleName, ['ngResource', 'fileupload', 'doclink', 'link']);
}

angular.module(moduleName)
    .factory('CommentsCollection', ['$resource', 'Comment', function($resource, Comment) {
        // set up a $resource for the all endpoint
        var resource = $resource('/api/comments/discussions', {}, {
            fetch: {
                method: 'GET',
                isArray: false,
                params: {
                    objects: '@objects',
                    limit: '@limit',
                    offset: '@offset',
                    sortDesc: '@sortDesc',
                },

                /**
                 * Generate GET request from pagination object
                 *
                 * @param params
                 * @returns {string}
                 */
                paramSerializer: function(params) {
                    var urlSearchParams = new URLSearchParams();

                    angular.forEach(params, function(value, key) {
                        if (key === 'objects' && angular.isObject(value)) {
                            // ok value is {discuss: [1,2,3]}
                            Object.keys(value).map(function (key) {
                                urlSearchParams.set('objects[' + key + ']', value[key].join(','))
                            });
                        } else {
                            urlSearchParams.set(key, value);
                        }
                    });

                    return urlSearchParams.toString();
                }
            }
        });

        /**
         * Get collection of the comments filtered by columns aggregation_id and object_id
         *
         * @param objectIds
         * @param limit
         * @param offset
         * @param sortDesc
         * @constructor
         */
        function CommentsCollection(objectIds, limit, offset, sortDesc) {
            if (objectIds !== undefined) {
                this.objects = {
                    discuss: objectIds
                };
            }

            this.offset = offset;
            this.limit = limit;
            this.sortDesc = true;

            if (sortDesc !== undefined)
                this.sortDesc = sortDesc;

            this.comments = []; // Comment instances
            this.paging = {};   // { offset, limit, total, prev, next }
        }

        CommentsCollection.prototype = {
            /**
             * Fetch page of comments from the server, wrap each in a Comment,
             * and then call back with (err, this).
             */
            loadPage: function(callback) {
                var self = this;
                resource.fetch(
                    {
                        objects: this.objects,
                        limit: this.limit,
                        offset: this.offset,
                        sortDesc: this.sortDesc,
                    },
                    function (response) {
                        // wrap raw data items in Comment model
                        angular.forEach(response.data, function(raw) {
                            var comment = new Comment();
                            comment.load(raw);
                            self.comments.push(comment);
                        });

                        // copy over paging
                        self.paging = response.paging || {};
                        callback && callback(null, self);
                    },
                    function (err) {
                        callback && callback(err);
                    }
                );
            },

            /**
             * Get the next page
             */
            loadNextPage: function(callback) {
                if (!this.paging.next) {
                    return callback && callback(new Error('No next page'));
                }

                // extract offset
                var parsedUrl = new URL(this.paging.next, window.location.origin);
                var offset = parseInt(parsedUrl.searchParams.get('offset'), 10);

                if (offset)
                    this.offset = offset;

                this.loadPage(callback);
            },

            setOffset: function (offset) {
                this.offset = offset;
            }
        };

        return CommentsCollection;
    }]);
