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

define(['hp/model/TaskFollower',
        'hp/core/LinkTargetBuilder',
        'hp/model/Session',
        'hp/core/Localizer'],
function(taskFollower, linkTargetBuilder, session, localizer) {"use strict";

    var TaskNotificationFormatter = ( function() {

        var TASK_STATE_TO_STATUS = {
                New: 'info',
                Running: 'info',
                Completed: 'ok',
                Error: 'error',
                Warning: 'warning',
                Terminated: 'disabled',
                Killed: 'disabled'
        };
        var DEFAULT_ACTIONS = [ "{addLink}", "{removeLink}", "{supportDump}"];

        /**
         * @constructor
         * @type {TaskNotificationsFormatter}
         */
        function TaskNotificationFormatter() {

            var supportDump = 'support dump';
            var supportDumpLink = session.canPerformAction('appliance', 'Read') ?
                    '<a href="#/settings/support/createSupportDump">' + supportDump + '</a>' : supportDump;
            var self = this;

            function getDefaultSubstitutions(task) {
                var substitutions = [{ token: 'supportDump', name: supportDumpLink }];

                return substitutions;
            }

            function getSubstitutions(task) {

                var addLink = linkTargetBuilder.makeLink(localizer.getString('core.details.add'),
                        null, 'add', task.category, 'Create', null);
                var removeName = 'Remove';
                //var removeLink = session.canPerformAction(task.category, 'Delete') ?
                //        '<a id="">' + removeName + '</a>' : removeName;

                var substitutions = [
                                     { token: 'addLink', name: addLink },
                                     { token: 'removeLink', name: removeName }
                                     ];

                return substitutions.concat(self.getDefaultSubstitutions(task));
            }
            function getSubstitutionsForError(task, taskError) {
                var substitutions = null;

                if (taskError && taskError.data) {
                    try {
                        substitutions = JSON.parse(taskError.data.substitutions ? taskError.data.substitutions : taskError.data);
                    }
                    catch(err) {
                        // just leave substitutions null if we can't turn it into a real object
                    }
                }

                if (!substitutions || ('array' !== $.type(substitutions))) {
                    substitutions = [];
                }

                return substitutions.concat(self.getSubstitutions(task));
            }

            /**
             * Format a task error object into text and links as appropriate
             *
             * @param {Object} taskError an error object from TaskResource.taskErrors[]
             */
            function formatTaskError(task, taskError) {
                var message,
                    text,
                    separator = (task.taskErrors.length === 1) ? '<br><b>Resolution: </b>' : ' ', // TODO I18N
                    resolution,
                    substitutions;

                substitutions = self.getSubstitutionsForError(task, taskError);

                resolution = (taskError.recommendedActions ? taskError.recommendedActions.join(' ') : '');
                message = (taskError.details ? taskError.details : taskError.message);

                text = (message ? message : '') + separator + resolution;

                return linkTargetBuilder.replaceTokensWithLinks(text, substitutions);
            }

            function getDetails(task) {
                var items = [];
                if (taskFollower.isTaskFinished(task)) {
                    if (task.taskErrors) {
                        $.each(task.taskErrors, function (i, taskError) {
                            items.push(formatTaskError(task, taskError));
                        });
                    }
                }
                else if (taskFollower.isTaskRunning(task)) {
                    if (task.progressUpdates) {
                        $.each(task.progressUpdates, function(i, item) {
                            items.push(item.statusUpdate);
                        });
                    }
                }
                return items.join('<br>');
            }

            function errorsHasToken(task, token) {
                return  task.taskErrors ? JSON.stringify(task.taskErrors).indexOf(token) !== -1 : false;
            }

            function getProcessedActions(task) {
                var rawActions = self.getActions(task),
                    substitutions = self.getSubstitutions(task),
                    actions = [];

                if (!rawActions) {
                    rawActions = [];
                }

                $.each(rawActions, function(i, action) {
                     actions.push(linkTargetBuilder.replaceTokensWithLinks(action, substitutions));
                });

                $.each(DEFAULT_ACTIONS, function(i, action) {
                    if (($.inArray(action, rawActions) === -1) && errorsHasToken(action)) {
                        actions.push(linkTargetBuilder.replaceTokensWithLinks(action, substitutions));
                    }
                });

                return actions;
            }

            function getNotification(task) {
                var notif = {
                    uri: task.uri,
                    owner: task.owner,
                    status: self.getStatus(task),
                    changing: taskFollower.isTaskRunning(task),
                    summary: self.getSummary(task),
                    timestamp: task.modified,
                    sourceUri: task.associatedResourceUri,
                    sourceName: self.getSourceName(task),
                    progress: self.getProgress(task),
                    details: self.getDetails(task),
                    dismiss: self.getDismiss(task),
                    step: self.getStep(task)
                };

                notif.actions = getProcessedActions(task);

                return notif;
            }

            function getDefaultActions(task) {
                // no actions by default
                return [];
            }

            this.getStatus = function(task) {
                var type = TASK_STATE_TO_STATUS[task.taskState];
                return (type)?type:"info";
            };

            this.getNotification = getNotification;

            this.getDetails = getDetails;

            this.getDefaultActions = getDefaultActions;

            this.getActions = getDefaultActions;

            this.getSummary = function(task) {
                return task.name;
            };

            this.getProgress = function(task) {
                var progress;
                if (taskFollower.isTaskFinished(task)) {
                    progress = 0;
                }
                else {
                    if (task.computedPercentComplete) {
                        progress = task.computedPercentComplete;
                    }
                    else if (task.totalSteps || task.expectedDuration) {
                        progress = 1; // force progress bar to show up.
                    }
                }
                return progress;
            };

            this.getStep = function(task) {
                var step;
                if (!taskFollower.isTaskFinished(task) &&
                    task.progressUpdates && (task.progressUpdates.length > 0)) {
                    step = task.progressUpdates[task.progressUpdates.length - 1].statusUpdate;
                }
                return step;
            };

            this.getSourceName = function(task) {
                return undefined;
            };
            
            this.getDismiss = function(task) {
                return undefined;
            };

            this.getSubstitutionsForError = getSubstitutionsForError;

            this.getDefaultSubstitutions = getDefaultSubstitutions;

            this.getSubstitutions = getSubstitutions;

            this.formatTaskError = formatTaskError;
        }
        return TaskNotificationFormatter;
    }());

    return TaskNotificationFormatter;
});