// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define(['hp/core/EventDispatcher',
    'hp/services/IndexFilter',
    'hp/core/LinkTargetBuilder',
    'hp/model/DevelopmentSettings',
    'hp/core/Localizer',
    'hp/services/Log'],
function(EventDispatcher, IndexFilter, linkTargetBuilder,
    settings, localizer, log) { "use strict";

    var IndexPresenter = (function() {

        /**
         * @constructor
         * @type {IndexPresenter}
         */
        function IndexPresenter() {
            var dispatcher = new EventDispatcher();
            var timer = null;
            var resource = null;
            var defaultMetaQuery = null;
            var awaitingResults = false;
            var refreshing = false;
            var active = false;

            // Prototyping method to make sonar happy
            var getIndexResults;

            /**
             * @private
             * Start polling the index service for results.
             */
            function restartTimer() {
                if (active && settings.getRefreshInterval()) {
                    clearTimeout(timer);
                    timer = setTimeout(function () {
                        refreshing = true;
                        getIndexResults();
                    }, settings.getRefreshInterval());
                }
            }

            // Method prototyped above to make sonar happy
            getIndexResults = function() {
                if (! awaitingResults) {
                    awaitingResults = true;
                    resource.getIndexResults({
                        error: function () {
                            awaitingResults = false;
                            restartTimer();
                        },
                        success: function () {
                            awaitingResults = false;
                            restartTimer();
                        }
                    });
                }
            };

            function resetGetResults(doGet) {
                clearTimeout(timer);
                refreshing = false;
                if (doGet) {
                    getIndexResults();
                }
            }

            function showMore() {
                var newFilter = new IndexFilter(resource.getIndexFilter());
                newFilter.bumpCount();
                resource.setIndexFilter(newFilter);
            }

            function onIndexResultsChanged(indexResults) {
                indexResults.refreshed = refreshing;
                dispatcher.fire("indexResultsChange", indexResults);
            }

            function onIndexResultsError(errorInfo) {
                dispatcher.fire("indexResultsError", errorInfo);
            }

            function onFilterChange(filter) {
                refreshing = false;
                resetGetResults(typeof filter.data.category !== "undefined");
                dispatcher.fire("filterChange", filter);
            }

            function unregisterListeners() {
                resource.off('indexResultsChange', onIndexResultsChanged);
                resource.off('indexResultsError', onIndexResultsError);
                resource.off("filterChange", onFilterChange);
            }

            function registerListeners() {
                resource.on('indexResultsChange', onIndexResultsChanged);
                resource.on('indexResultsError', onIndexResultsError);
                resource.on("filterChange", onFilterChange);
            }

            this.init = function(args) {
                active = true;
                resource = args.resource;
                defaultMetaQuery = args.defaultMetaQuery;

                if (defaultMetaQuery) {
                    var filter = new IndexFilter(resource.getIndexFilter());
                    filter.setUserQuery(defaultMetaQuery);
                    resource.setIndexFilter(filter);
                }

                registerListeners();
                resetGetResults(false);
            };

            /**
             * @public
             * Stop the timer polling of the index service.
             */
            this.pause = function () {
                active = false;
                timer = clearTimeout(timer);
                timer = null;
                unregisterListeners();
            };

            /**
             * @public
             * Resume the timer polling of the index service.
             */
            this.resume = function () {
                active = true;
                registerListeners();
            };

            this.haveMore = function () {
                return resource.haveMore();
            };

            this.showMore = showMore;

            this.getFilterValue = function (name) {
                var filter = resource.getIndexFilter();
                var result = 'all';
                if (filter) {
                    var value = filter.getProperty(name);
                    if (value) {
                        result = value;
                    }
                }
                return result;
            };

            this.setFilterValue = function (name, value) {
                var setIndexFilter = false;
                var filter = new IndexFilter(resource.getIndexFilter());
                if (value && 'all' !== value) {
                    if (filter.setProperty(name, value)) {
                        setIndexFilter = true;
                    }
                } else {
                    if (name === 'category') {
                        filter.resetCategory();
                        setIndexFilter = true;                            
                    } else {  
                        setIndexFilter =  filter.unsetProperty(name);
                    }
                }
                if (setIndexFilter) {
                    resource.setIndexFilter(filter);    
                }
            };

            this.setMetaFilter = function (query) {
                var filter = new IndexFilter(resource.getIndexFilter());
                filter.reset();
                filter.resetCategory();
                filter.setUserQuery(query);
                resource.setIndexFilter(filter);
            };

            this.resetFilters = function (names) {
                var filter = new IndexFilter(resource.getIndexFilter());
                var length = names.length;
                for (var i=0; i<length; i++) {
                    filter.unsetProperty(names[i]);
                }
                filter.resetToDefaults();
                if (defaultMetaQuery) {
                    filter.setUserQuery(defaultMetaQuery);
                }
                resource.setIndexFilter(filter);
            };

            this.getSearchText = function () {
                var filter = resource.getIndexFilter();
                return (filter ? filter.getUserQuery() : '');
            };
            
            //@public
            //
            //Returns the message to display when an index request hasn't 
            //returned any results.  Either returns a message saying that there
            //aren't any matches, a message saying that there aren't any resources,
            //or a message saying that we are loading the data.
            //
            //@param indexResults The results from an index request (optional)           
            this.getEmptyMessage = function (indexResults) {
                if (indexResults &&
                    indexResults.unFilteredTotal &&
                    indexResults.unFilteredTotal > 0) {
                    return localizer.getString('core.master.noMatches');
                }
                var categoryLabel = linkTargetBuilder.
                    categoryLabel(resource.category).toLowerCase();
                if (resource.haveContacted()) {
                    return localizer.getString('core.master.noItems', [categoryLabel]);
                } else {
                    return localizer.getString('core.master.loadingItems', [categoryLabel]);
                }
            };

            /**
             * Add a listener for a specified event.
             * @param {string} eventName The name of the event.
             * @param {function(...)}
             */
            this.on = function (eventName, callback) {
                dispatcher.on(eventName, callback);
            };

            this.off = function (eventName, callback) {
                dispatcher.off(eventName, callback);
            };
        }

        return IndexPresenter;
    }());

    return IndexPresenter;
});
