// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['fs/services/tasks/TasksService',
    'hp/core/EventDispatcher',
    'hp/core/NotificationFormatter',
    'hp/model/DevelopmentSettings'], 
function(service, EventDispatcher, notificationFormatter, settings) {"use strict";

    var ActivityTaskPresenter = ( function() {

        /**
         * @constructor
         * @type {ActivityPresenter}
         */
        function ActivityTaskPresenter() {

            var dispatcher = new EventDispatcher();
            var expanded = {}; // task uri -> true
            var expandedCount = 0;
            var timer = null;
            var awaitingResult = {}; // task uri -> true
            
            function addNotifications(treeNode) {
                var task = treeNode.resource;
                task._notification = {category: 'tasks',
                    sourceCategory: task.associatedResource.resourceCategory};
                notificationFormatter.format(task._notification, task);
                
                var length = treeNode.children.length;
                for (var i=0; i<length; i++) {
                    addNotifications(treeNode.children[i]);
                }
            }
            
            function onTaskSuccess(tree) {
                delete awaitingResult[tree.resource.uri];
                // only if not removed
                if (expanded[tree.resource.uri]) {
                    // add notifications
                    addNotifications(tree);
                    dispatcher.fire('taskChange', tree);
                }
            }
            
            function getTask(uri) {
                // if there is no outstanding request for this
                // uri, then make the service call.
                if (! awaitingResult[uri]) {
                    awaitingResult[uri] = true;
                    service.getTaskTree(uri, {
                        success: onTaskSuccess,
                        error: function (errorInfo) {
                            // TBD
                            // If error occurs, clean up and allow retry
                            delete awaitingResult[uri];
                        }
                    });
                }
            }
            
            function getExpanded() {
                clearTimeout(timer);
                timer = null;
                $.each(expanded, function (uri, ignore) {
                    getTask(uri);
                });
                if (expandedCount > 0) {
                    timer = setTimeout(getExpanded,
                        settings.getRefreshInterval());
                }
            }

            /**
             * @public
             */
            this.init = function () {
                awaitingResult = {};
            };
            
            this.pause = function () {
                clearTimeout(timer);
                timer = null;
            };
            
            this.resume = function () {
                awaitingResult = {};
                if (expandedCount > 0) {
                    timer = setTimeout(getExpanded,
                        settings.getActivityRefreshInterval());
                }
            };
            
            this.expand = function (uri) {
                if (! expanded[uri]) {
                    expandedCount += 1;
                }
                expanded[uri] = true;
                getTask(uri);
                if (! timer) {
                    timer = setTimeout(getExpanded,
                        settings.getRefreshInterval());
                }
            };
            
            this.collapse = function (uri) {
                delete expanded[uri];
                expandedCount -= 1;
            };
            
            /**
             * @public
             * 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 new ActivityTaskPresenter();
    }());

    return ActivityTaskPresenter;
});
