// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
/*global clearTimeout*/
define(['hp/core/EventDispatcher',
    'hp/services/IndexService',
    'hp/model/map/Map',
    'hp/core/Router',
    'hp/core/UrlFragment',
    'hp/core/Style',
    'hp/model/DevelopmentSettings',
    'hp/services/Log'], 
function(EventDispatcher, indexService, Map, router, urlFragment, style, settings, log) {"use strict";

    var MapPresenter = ( function() {

        /**
         * @constructor
         * @type {MapPresenter}
         */
        function MapPresenter() {

            var dispatcher = new EventDispatcher();
            var history = []; // {name: name, uri: uri}
            var currentUris = null;
            var timer = null;
            var awaitingResults = false;
            var refreshing = false;
            var paused = false;
            //var getTime;
            
            var getMap; // for Sonar
            
            function restartTimer() {
                if (settings.getRefreshInterval() && !paused) {
                    clearTimeout(timer);
                    timer = setTimeout(function () {
                        refreshing = true;
                        getMap();
                    }, settings.getRefreshInterval());
                }
            }
            
            function onMapResult(data) {
                //var startTime = new Date();
                var map = new Map();
                
                map.init(data);
                map.refreshed = refreshing;
                //var endTime = new Date();
                //console.log('!!! map retrieved in', (startTime.getTime() - getTime.getTime()), 'ms, built in', (endTime.getTime() - startTime.getTime()), 'ms');
                if (map.selectedNode()) {
                    if (! refreshing) {
                        history.push({uri: data.rootUri,
                            name: map.selectedNode().name});
                    }
                    dispatcher.fire("mapChange", map);
                }
                awaitingResults = false;
                //var drawnTime = new Date();
                //console.log('!!! map retrieved in', (startTime.getTime() - getTime.getTime()), 'ms, built in', (endTime.getTime() - startTime.getTime()), 'ms, drawn in', (drawnTime.getTime() - endTime.getTime()), 'ms');
                restartTimer();
            }
            
            function onMapError(error) {
                awaitingResults = false;
                log.log(error);
                dispatcher.fire("mapError", error);
                restartTimer();
            }
            
            getMap = function() {
                if (! awaitingResults) {
                    awaitingResults = true;
                    //getTime = new Date();
                    
                    indexService.getMap({
                        uris: currentUris,
                        childLimit: style.related().summaryThreshold,
                        handlers: {
                            success: onMapResult,
                            error: onMapError
                        }
                    });
                }
            };
            
            function routeChange(locationArg) {
                var uris = urlFragment.getUris(locationArg);
                if (uris && uris.length > 0) {
                    refreshing = false;
                    currentUris = uris;
                    dispatcher.fire("mapChanging");
                    getMap();
                }
            }
            
            /**
             * @public
             */
            this.init = function (route) {
                router.watch(route + ' map', route + '($|/.*)',
                    {change: routeChange});
            };
            
            this.pause = function () {
                paused = true;
                clearTimeout(timer);
                timer = null;
            };
            
            this.resume = function () {
                paused = false;
                refreshing = false;
                restartTimer();
            };
            
            this.getHistory = function () {
                return history.slice(0, -1); // don't include current
            };
            
            /**
             * @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 MapPresenter();
    }());

    return MapPresenter;
});
