// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
/**
 * @type {iloFederationPresenter}
 */
 define(['hpsum/model/ilofederation/iloFederationResource',
    'hpsum/presenter/baseline/BaselinePresenter',
    'hp/services/IndexService',
    'hp/services/IndexFilter',
    'hp/core/Router',
    'hp/core/UrlFragment',
    'hp/core/LinkTargetBuilder',
    'hp/core/Notifications',
    'hp/core/EventDispatcher',
    'hp/services/REST',
    'hp/model/Session',
    'hp/core/Localizer'], 
    function (resource, baselinePresenter, indexService, IndexFilter, router, urlFragment, linkTargetBuilder,
        notifications, EventDispatcher,restService, session, localizer) {
        "use strict";


        var iloFederationPresenter = ( function() {

            /**
             * @constructor
             */
             function iloFederationPresenter() {

                var dispatcher = new EventDispatcher(),
                baselines = [],
                types = [],
                selectedName = '',
                selectedItem = '',
                lastLocation = '',
                lastAction = '',
                trackUri = null,
                initDone = false,
                aggregate = null,
                itemchange = null,
                allBaselines = null,
                nodesAdvOptions = [];
                var tMap={};

                var task = {
                    category : 'task',
                    name : 'Adding',
                    uri : '/task/task-' + (new Date()).getTime(),
                    status : 'unknown',
                    changing : true,
                    sourceUri : null,
                    sourceName : null,
                    date : null,
                    state : 'running',
                    progress : 10,
                    progressStep : 'Initializing',
                    owner : session.getUser()
                };

				
                //Added force (true) option to resource.getItem(), so that once SUG edit page closes
                //getdata() will be called forcefully instead of using stale data from selectedItems.
                function getItem(force) {
                	if(force == undefined)
                		force = false;
                    var uris = resource.getSelection().uris;
                    selectedName = '';
                    if (uris && uris.length > 0) {
                        resource.getItem(uris[0], {
                            //resource.getItem(resource.getSelection().uris[0], {
                                success : function(item) {
                                    selectedName = item.name;
                                    selectedItem = item;
                                    var index = $.inArray(item.hapi.type, types);
                                    if (index === -1)
                                        types.push(item.hapi.type);
                                    dispatcher.fire("itemChange", item);
                                },
                                error : function(errorMessage) {
                                    dispatcher.fire("itemError", errorMessage);
                                }
                            }, force);
                    }
                }
                
                function getAssociations() {
                    var uris = resource.getSelection().uris;
                    if (uris && uris.length > 0) {
                        indexService.getParentAndChildrenAssociations({
                            uri : uris[0],
                            parentDepth : 1,
                            childDepth : 1,
                            handlers : {
                                success : function(tree) {
                                    dispatcher.fire("associationsChange", tree);
                                },
                                error : function(errorMessage) {
                                    dispatcher.fire("associationsError", errorMessage);
                                }
                            }
                        });
                    }
                }

                function selectionChange(selection) {
                    dispatcher.fire("selectionChange", selection);
                    aggregate = null;
                    if (selection.uris) {
                        if (!selection.multiSelectId) {
                            // get the selected item
                            getItem();
                            //getAssociations();
                        } else {
                            // generate aggregate information
                            aggregate = {count: selection.uris.length,
                            //status:{ok: 0, warning: 0, error: 0, disabled: 0, unknown: 0},
                            sug_name:{ },
                            sug_status:{ },
                            sug_state:{ },
                            sug_id:{ }};
                            var indexResult;
                            var i=0;
                            $.each(selection.uris, function(index, uri) {
                                indexResult = resource.getIndexResultForUri(uri);
                                if(indexResult){
                                    var nodeId = uri.split("/");
                                    aggregate.sug_id[i] = nodeId[4];
                                    aggregate.sug_state[i] = indexResult.node_state;
                                    aggregate.sug_status[i] = indexResult.node_status;
                                    aggregate.sug_name[i] = indexResult.name;
                                    i++;
                                }
                            });
                            selectedName = aggregate.count + " servers";

                            dispatcher.fire("aggregateChange", aggregate);
                        }
                    }
                }

                function indexResultsCompare(last, latest)
                {
                    //Check if path has changed from last time.
                    var loc = router.location().split('/');
                    if((loc.length < 6) && (loc[2] == 'show'))
                        return false;
                    var location = loc[1];
                    var action = loc[2];

                    if(lastLocation != location || lastAction != action) {
                        lastLocation = location;
                        lastAction = action;
                        return false;
                    }
					if(last.name != latest.name)
					{
						return false;
					}
                    if((last.sug_state == latest.sug_state) && (last.sug_status  == latest.sug_status))
					{
                        return true;
					}
                    return false;
                }
            
            
                function onAddSuccess(data,message)
                {
                    task.name = "Added";
                    task.status = 'ok';

                    var notif = {
                        summary: task.name,
                        status: task.status,
                        sourceName: task.sourceName,
                        sourceUri: task.sourceUri,
                        progress: task.progress,
                        step: task.progressStep
                    };

                    var summary = data.hapi.hmessage;
                    //
                    if(message)
                    {
                         summary = message;

                    }  

                    notif.summary = summary;
                    notif.status = task.status;
                    notifications.add(notif, true);

                    if (task.sourceUri === trackUri) {
                        dispatcher.fire('notificationChange', notif);
                    }

                }

                function onAddError()
                {

                }

                function onNodeStatusSuccess(data)
                {
                   if(!data.hapi.node_status.node_phase.match(/initialize/i))
                   {
                        clearInterval(tMap[data.hapi.node_status.node_id]);
                        resource.getIndexResults();
                        delete tMap[data.hapi.node_status.node_id];
                    }
                }   

                function onNodeStatusError(){

                }

                this.fireAggregate = function()
                {
                    dispatcher.fire("aggregateChange", aggregate);
                };



                this.fireItemChange = function()
                {
                    dispatcher.fire("itemChange", itemchange);
                };

                this.otheroption = function(item, handlers) 
                {

                    var sessionurl = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/getattributes';
                    restService.getURI(sessionurl, handlers);

                };

                this.getbaseline = function(item, handlers) {

                    var sessionurl = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/getupdatelist';
                    restService.getURI(sessionurl, handlers);

                };
				this.getBaselineDetailsforId = function(baselineId) {
                    var iter;
                    if (baselineId == '')
                        return null;
                    for ( iter = 0; iter < baselines.length; iter++) {
                        if (baselines[iter].id.match(baselineId))
                            return baselines[iter];
                    }
                    return null;
                };


                this.deploy = function(item, handlers) 
                {
                    var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/deploy';
                    var object = {
                        hapi : {
                            deploy_mode : item.deploy_mode,
                            deploy_url:item.url_or_path,
                            server_type_filter: item.server_type_filter
                        }
                    };
                    restService.postObject(uri, object ,{
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                                resource.getIndexResults();
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function() {
                            handlers.error()
                        }
                    },null);
                };
				
				this.validate = function(item, handlers) 
                {
                    var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/validate';
                    var object = {
                        hapi : {
							validate_url : item.url_path
                        }
                    };
                    restService.postObject(uri, object ,{
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data);
                        },
                        error : function() {
                            handlers.error()
                        }
                    },null);
                };

                this.setattribute = function(item, optiondetails, handlers) {
                     var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/setattributes';
                     restService.postObject(uri, optiondetails, "", {
                        success : function(data) {
                        		//call getdata() forcefully to retrieve modified SUG data
                        		getItem(true);
                                handlers.success(data);
                        },
                        error : function() {
                            handlers.error();
                        }
                    }, {});
                 };


                this.analysis = function(item, complist, handlers) {
                    var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/analysis';
                    restService.postObject(uri, complist, "", handlers, {});
                };

                this.getAllScalableObjects = function(handlers) {
                    var uri = '/session/' + session.getToken() + '/node/ScalableUpdate/index';
                    var object = null;
                    restService.getURI(uri, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function(error) {
                            handlers.error(error);
                        }
                    });
                };

                this.getSUGData = function(item, handlers) {
                    var uri = '/session/' + session.getToken() + '/node/ScalableUpdate' + item.sug_id + '/getdata';
                    restService.postObject(uri, null, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data, item);
                        },
                        error : function() {
                            handlers.error(item);
                        }
                    }, null);
                };

                function getBaselinesSuccess(data, handlers) 
                {
                    baselines = [];
                    var i = 0, baselineid;
                    var paths = [];
                    for ( i = 0; i < data.length; i++) {
                      if (data[i].hasOwnProperty("baseline_id")) {
                        var str = data[i].baseline_url;
                        str = str.replace(new RegExp(/\\/g),"/");

                        var obj = {
                            id : data[i].locationid + '/' + data[i].baseline_id,
                            name : data[i].baseline_name + ' at ' + str,
                            uri : data[i].baseline_uri,
                            url : data[i].baseline_url
                        };
                        baselines.push(obj);
                    }
                    }
                    if (handlers)
                        handlers.success(baselines);
                }

                function getBaselinesError(msg, handlers) {
                    if (handlers)
                        handlers.error(msg);
                }


                this.abortNode = function(node_id, handlers) {
                    var uri = '/session/' + session.getToken() + '/node/' + node_id + '/abort';
                    restService.postObject(uri, null, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function() {
                            handlers.error()
                        }
                    }, null);
                };

                this.abortAction = function(item, handlers) {
                    var uri = '/session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/abort';
                    restService.postObject(uri, null, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function() {
                            handlers.error()
                        }
                    }, null);
                };

                //Activate REST API provides reboot now functionality for node
                this.rebootNode = function(node_id, handlers) {
                    var uri = '/session/' + session.getToken() + '/node/' + node_id + '/activate';
                    restService.postObject(uri, null, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function() {
                            handlers.error();
                        }
                    }, null);
                };


                this.deleteItem = function(item, handlers) {
                    var uri = '/session/' + session.getToken() + '/node/ScalableUpdate/' + item.sug_id + '/remove';
                    restService.postObject(uri, null, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                                resource.removeSelectedUri('/Session/' + session.getToken() + '/Node/ScalableUpdate/' + item.sug_id + '/getdata');
                                // add a task
                                task.sourceName = item.sug_name;

                                var notif = {
                                    summary : localizer.getString('hpsum.ilofederation.deletemsg'),
                                    status : 'ok',
                                    sourceName : task.sourceName,
                                };
                                notifications.add(notif, true);
                                resource.getIndexResults();
                            } else
                            handlers.error(data.hapi.hmessage);
                        },
                        error : function() {
                            handlers.error();
                        }
                    }, null);
                };

                this.getBaselineDetailsforId = function(baselineId) {
                    var i;
                    if (baselineId == '')
                        return null;
                    for ( i = 0; i < baselines.length; i++) {
                        if (baselines[i].id.match(baselineId))
                            return baselines[i];
                    }
                    return null;
                };

                this.getBaselineDetailsforName = function(baselineName)
                {
                    var i;
                    if(baselineName == '')
                        return null;
                    for (i=0; i<baselines.length;i++){
                        if(baselines[i].name.match(baselineName))
                            return baselines[i];
                    }
                };
                this.getAllBaselines = function(handlers) {
                   baselinePresenter.getBaselines({
                    success : function(data) {
                        getBaselinesSuccess(data, handlers)
                    },
                    error : function(msg) {
                        getBaselinesError(msg, handlers);
                    }
                });
                };

                this.getGUAllBaselines = function(handlers) {
                   baselinePresenter.getGUBaselines({
                    success : function(data) {
                        getBaselinesSuccess(data, handlers)
                    },
                    error : function(msg) {
                        getBaselinesError(msg, handlers);
                    }
                });
                };

                this.getAllNodes = function(handlers) {
                    var uri = '/session/' + session.getToken() + '/node/index';
                    var thishandlers = {
                        success : function(data) {
                            handlers.success(data);
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };
                    restService.getURI(uri, thishandlers);
                };

                this.haveItems = function() {
                    return resource.haveSome();
                };

                this.selectionLabel = function() {
                    return selectedItem.hapi.name;
                };

                this.getAllNodeTypes = function() {
                    return types;
                };
                this.getSUGStatus = function(item, handlers) {
                    var uri = '/session/' + session.getToken() + '/Node/ScalableUpdate/' + item.sug_id + '/getstatus';
                    var thishandlers = {
                        success : function(data) {
                            handlers.success(data);
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };
                    restService.getURI(uri, thishandlers);
                };
             

               
                this.startInventory = function(item, handlers) {
                    var uri = '/session/' + session.getToken() + '/Node/ScalableUpdate/' + item.sug_id + '/inventory';
                    var object = {
                        hapi : {
                            baselines : {
                                remove_existing_baselines:'true',
                                baseline : item.baselines,
                            },
                            ip : item.ip,
                            username : item.username,
                            password : item.password
                        }
                    };
                    restService.postObject(uri, object, {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                                resource.getIndexResults();
                            }
                            else
                                handlers.error(data.hapi.hmessage);
                        },
                        error: function (){
                            handlers.error()
                        }
                    }, null);
                };

                this.refresh = function(handlers,check){
                    var uri = '/session/' + session.getToken() + '/Node/ScalableUpdate/' + 'findgroups'
                    var request = {
                        hapi: {
                           just_check:check
                        }

                    };
                    var thishandlers = {
                        success : function(data) {
                                
                                handlers.success(data);
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };
                    restService.postObject(uri, request, "", thishandlers, {});
                }


                this.addGroup = function(item, handlers) {
                    // add a task
                    task.sourceName = item.group_name;
                    task.sourceUri = item.uri;
                    task.date = item.date;

                    item.status = 'unknown';
                    resource.addScalableGroup(item, {
                        success : function(data) {
                            onAddSuccess(data);
                            
                            resource.getIndexResults();
                            dispatcher.fire('itemChange', item);
                            handlers.success(data);
                        },
                        error : function (data){
                         onAddError();
                         handlers.error(data);
                     }
                    });
                    trackUri = item.uri;
                    resource.getIndexResults();
                };

                

            this.refreshIndexResults = function() {
                resource.getIndexResults();
            };

            this.setFilter = function(value) {
                var filter = resource.getIndexFilter();
                if (filter) {
                    if (filter.getUserQuery == value)
                        return;
                }
                var newFilter = new IndexFilter();
                newFilter.data.userQuery = value;
                resource.setIndexFilter(newFilter);
                resource.getIndexResults();
            };

                /**
                 * @public
                 */
                 this.init = function() {
                    resource.setCompareResourcesFunction(indexResultsCompare);
                    resource.on("selectionChange", selectionChange);
                    initDone = true;
                    this.getAllBaselines();
                };

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

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

                this.getFWBaseline = function(baselines) {
                    var iter;
                    if (baselines == undefined){
                        return {
						fwbaseline : null,
						addpackage : null
						};
					}
                    if (baselines.length == 0){
                        return {
						fwbaseline : null,
						addpackage : null
						};
					}
					var fwbaseline = null, addpackage = null;
                    for (var iter = 0; iter < baselines.length; iter++) 
					{
                        var baseline = this.getBaselineDetailsforId(baselines[iter]);
                        if (baseline) 
						{
                            if (!baseline.name.match(/^Additional Package/i)) {
								fwbaseline = baseline;
                            }
                            else
							{
								addpackage = baseline;
							}
                        }
                    }
					return {
							fwbaseline : fwbaseline,
							addpackage : addpackage
							};
                };
				this.getBaselineOrPkg = function(baselines) {
                    var i;
                    var bl = null;
                    var pkg = null;
                    var baseline = null;
                    if (baselines == undefined)
                        return null;
                    if (baselines.length == 0)
                        return null;
                    for (var i = 0; i < baselines.length; i++) {
                       baseline = this.getBaselineDetailsforId(baselines[i]);
                       if (baseline) {
                        if (!baseline.name.match(/^Additional Package/i)) {
                            bl = baseline;
                        }
                        else{
                            pkg = baseline;
                        }
                    }
                }
                if(bl != null)
                   return bl;
               else
                   return pkg;
           };

           this.allBaselines = function() {
            return allBaselines;
        };
        this.getResetLink = function() {
            var result = null;
            if (session.canPerformAction('NODE', 'ADD')) {
                var resource = router.location().split('/');
                resource = resource[1];
                result = linkTargetBuilder.makeLink(localizer.getString('hpsum.node.refresh'), null, 'show', resource, 'SHOW');
            }
            return result;
        };

       this.getAddLink = function() {
                    var result = null;
                    if (session.canPerformAction('ILOFEDERATION', 'ADD')) {
                        result = linkTargetBuilder.makeLink(localizer.getString('hpsum.ilofederation.addGroup'), null, 'add', 'ilofederation', 'ADD');
                    }
                    return result;
                };

          this.createReport = function(request, handlers) {
                    var uri = "Session/" + session.getToken() + "/report/create";
                    var thishandlers = {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else {
                                handlers.error(data.hapi.hmessage);
                            }
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };
                    restService.postObject(uri, request, "", thishandlers, {});

                };

                this.generateReport = function(reportId, handlers) {
                    var uri = "Session/" + session.getToken() + "/report/" + reportId + "/generate";
                    var thishandlers = {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else {
                                handlers.error(data.hapi.hmessage);
                            }
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };

                    restService.postObject(uri, null, "", thishandlers, {});
                };

                this.getReportStatus = function(reportId, handlers) {
                    var uri = '/session/' + session.getToken() + '/report/' + reportId + '/getstatus';
                    var thishandlers = {
                        success : function(data) {
                            if (data.hapi.hcode == 0) {
                                handlers.success(data);
                            } else {
                                handlers.error(data.hapi.hmessage);
                            }
                        },
                        error : function(errorInfo) {
                            handlers.error(errorInfo);
                        }
                    };
                    restService.getURI(uri, thishandlers);
                };

                this.getAllReports = function(handlers) {
                   var uri = '/session/'+session.getToken() + '/report/index';
                   restService.getURI( uri, {
                       success: function(data){
                          if(data.hapi.hcode == 0){
                             handlers.success(data);
                         }
                         else {
                             handlers.error(data.hapi.hmessage);
                         }
                     },
                     error: function (error){
                      handlers.error(error);
                  }
              });
               };

               this.deleteReport = function(item, handlers) {
                   var uri = '/session/' + session.getToken() + '/report/' + item.report_id + '/remove';
                   var object = {
                      hapi : {
                         report_id : item.report_id
                     }
                 };
                 restService.postObject(uri, object, {
                  success : function(data) {
                     if (data.hapi.hcode == 0) {
                        handlers.success(data);
                    } else {
                        handlers.error(data.hapi.hmessage);
                    }
                },
                error : function(data) {
                 handlers.error(data);
             }
         }, null);
             };

             this.restore = function(nodeId) {
                var uri = '/Session/' + session.getToken() + '/node/' + nodeId + '/restore';
                restService.postObject(uri, null, {
                    success : function(data) {
                        resource.getIndexResults();
                    },
                    error : function() {
                    }
                }, null);
            };

            this.getUpdateList = function(sug_id,handlers){
                var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + sug_id + '/getupdatelist';
                restService.getURI(uri , handlers);

            };

            this.getComponentLogs = function(sug_id , componentlist , handlers )
            {
                var uri = '/Session/' + session.getToken() + '/node/ScalableUpdate/' + sug_id + '/getcomponentlogs';
                restService.postObject(uri, 
                {
                  hapi: { 
                    components: { component: componentlist } 
                }
            },"" , 
            handlers , {} );
            };
            
            this.setNodeForAdvOptions = function(node) {
                nodesAdvOptions.push(node);
            };
            this.getNodesForAdvOptions = function() {
                return nodesAdvOptions;
            };

			

            /**
             * Add a listener for a specified event.
             * @public
             * @param {string} eventName The name of the event.
             * @param {function(...)}
             */
             this.on = function(eventName, callback) {
                var uris;
                dispatcher.on(eventName, callback);
                    // fire initial state
                    switch (eventName) {
                        case 'selectionChange':
                        callback(resource.getSelection());
                        break;
                        case 'itemChange':
                        uris = resource.getSelection().uris;

                        if ((uris[0] == undefined) && selectedItem) {
                           uris[0] = selectedItem.hapi.sug_uri + '/getdata';                            	
                       }
                       if (uris && uris.length === 1) {
                                //var url = resource.getSelection().uris[0].replace(/enclosure|fc_switch|windows|linux|vmware|switch|host/, 'node');
                                resource.getItem(uris[0], {
                                    success : callback
                                });
                                // resource.getItem(uris[0], {success: callback});
                            }
                            break;
                            case 'itemError':
                            uris = resource.getSelection().uris;
                            if (uris && uris.length === 1) {
                                //var url = resource.getSelection().uris[0].replace(/enclosure|fc_switch|windows|linux|vmware|switch|host/, 'node');
                                resource.getItem(uris[0], {
                                    error : callback
                                });
                                // resource.getItem(uris[0], {success: callback});
                            }
                            break;
                        }
                    };

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

                return new iloFederationPresenter();
            }());

return iloFederationPresenter;
});