// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
/**
 * @type {DashboardCategoryPresenter}
 */
define(['hp/services/IndexService',
    'hp/services/ResourceService',
    'hp/services/IndexFilter',
    'hp/core/EventDispatcher'], 
function(indexService, resourceService, IndexFilter, EventDispatcher) {"use strict";

    var DashboardCategoryPresenter = ( function() {

        /**
         * @constructor
         */
        function DashboardCategoryPresenter() {
          
            var dispatcher = new EventDispatcher();
            var configuration;
            var lastTotal = 0;
            
            function getSummary() {
                var pending = configuration.statuses.length;
                var summary = {
                        category: configuration.category,
                        total: lastTotal
                    };
                
                $.each(configuration.statuses, function(index, status) {
                    var filter = new IndexFilter();
                    filter.ensureDefaults(configuration.category, 0, 0);
                    filter.setProperty('status', status.value);
                    summary[status.status] = -1;
                    indexService.getFilteredIndexResources(filter, {
                        success: function (indexResults) {
                            pending -= 1;
                            summary[status.status] = indexResults.total;
                            if (0 === pending) {
                                dispatcher.fire('summaryChange', summary);
                            }
                        },
                        error: function(errorInfo) {
                            pending -= 1;
                            if (0 === pending) {
                                dispatcher.fire('summaryChange', summary);
                            }
                        }
                    });
                });
            }

            function getUtilization(utilIndex, utilConfig) {
                var utilization = {
                        label: utilConfig.label,
                        segments: [],
                        type: utilConfig.type,
                        index: utilIndex,
                        total: lastTotal
                    };
                var resource = utilConfig.resource;
                var total = 0;
                
                var segments;
                var remainingSegment = {
                    label: utilConfig.other_label ? utilConfig.other_label : '',
                    query: '',
                    status: 'unknown',
                    total: lastTotal,
                    other_link: utilConfig.other_link,
                    isRemainingSegment: true
                };
                
                
                if (utilization.type === 'status') {
                    // define the segments from known statuses
                    segments = $.map(configuration.statuses, function(status, index) {
                        return {label: status.value,
                            query: 'status:' + status.value,
                            status: status.status };
                    });
                }
                else {
                    segments = utilConfig.segments ? utilConfig.segments.slice(0) : [];
                }
                
                if (utilConfig.category) {
                    // we have a different category for this graph. It needs it's
                    // remaining segment calculated from a different total.
                    segments.push({label: '', isTotal: true});
                }
                
                var pending = segments.length;
                var otherQuery = '';
                
                $.each(segments, function (index, segment) {
                    var resultSegment = {
                            label: segment.label,
                            query: segment.query,
                            status: segment.status,
                            color: segment.color,
                            properties: segment.properties
                        };
                    if (!segment.isTotal) {
                        utilization.segments.push(resultSegment);
                    }

                    var handler = function (indexResults) {
                        pending -= 1;
                        resultSegment.total = indexResults.total;
                        
                        // create 'other' query
                        if (resultSegment.total > 0 && resultSegment.query && 
                                resultSegment.query.length > 0) {
                            if(otherQuery.length > 0) {
                                otherQuery+= ' ';
                            }
                            otherQuery+='NOT ' + resultSegment.query;
                        }
                        
                        if (segment.isTotal) {
                            utilization.total = indexResults.total;
                        }
                        else {
                            total += indexResults.total;
                        }
                        if (0 === pending) {
                            remainingSegment.total = utilization.total - total;
                            if (remainingSegment.total > 0 && otherQuery.length > 0) {
                                remainingSegment.query = otherQuery;
                            }
                            // put remaining segment last
                            utilization.segments.push(remainingSegment);
                            dispatcher.fire('utilizationChange', utilization);
                        }
                    };
                    
                    var filter = new IndexFilter();
                    var category = utilConfig.category ? utilConfig.category : configuration.category;
                    filter.ensureDefaults(category, 0, 0);
                    if (segment.query) {
                        filter.setUserQuery(segment.query);
                    }
                    if (segment.properties) {
                        filter.setProperties(segment.properties);
                    }
                    if (segment.callback) {
                        segment.callback({success: handler});
                    }
                    else if (resource) {
                        //filter.data.count= -1; // RMs seem to always set total=count
                        //                       // if there are more than count results
                        resourceService.getFilteredResources(
                            segment.uri ? segment.uri : resource,
                            filter, {success: handler });
                    }
                    else {
                        indexService.getFilteredIndexResources(filter,
                            {success: handler} );
                    }
                });
            }
            
            function onGetTotalSuccess(indexResults) {
                lastTotal = indexResults.total;

                if (indexResults.total > 0) {
                    getSummary();
                    if (configuration.utilization) {
                        if ($.isArray(configuration.utilization)) {
                            $.each(configuration.utilization, getUtilization);
                        }
                        else {
                            getUtilization(0, configuration.utilization);
                        }
                    }
                }
                else {
                    dispatcher.fire('summaryChange', { category: configuration.category, total: 0 });
                }
            }
            
            this.getStatuses = function() {
                return configuration.statuses;
            };
            
            /**
             * @public
             */
            this.init = function (configurationArg) {
                configuration = configurationArg;
            };
            
            this.resume = function () {
            };
            
            this.pause = function () {
            };
            
            this.update = function () {
                var filter = new IndexFilter();
                filter.ensureDefaults(configuration.category, 0, 0);
                indexService.getFilteredIndexResources(filter, { success: onGetTotalSuccess });
            };
            
            /**
             * Add a listener for a specified event.
             * @public
             * @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 DashboardCategoryPresenter;
    }());

    return DashboardCategoryPresenter;
});
