/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
import template from "./detail.template.html";
import modalTemplate from './kilt.modal.template.html';
import {makeTaskStubFromWorkflowRecord} from "../activities.controller";
import jsyaml from 'js-yaml';
import runWorkflowModalTemplate from "../../run-workflow-modal.template.html";
import {runWorkflowController} from "../../inspect.controller";

export const detailState = {
    name: 'main.inspect.activities.detail',
    url: '/:activityId?workflowId?workflowLatestRun',
    template: template,
    controller: ['$scope', '$state', '$stateParams', '$location', '$log', '$uibModal', '$timeout', '$sanitize', '$sce', 'activityApi', 'entityApi', 'brUtilsGeneral', DetailController],
    controllerAs: 'vm',
}
function DetailController($scope, $state, $stateParams, $location, $log, $uibModal, $timeout, $sanitize, $sce, activityApi, entityApi, Utils) {
    $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);

    const {
        applicationId,
        entityId,
        activityId,
    } = $stateParams;
    $scope.workflowId = $stateParams.workflowId;

    let vm = this;
    vm.redirectToWorkflowLatestRun = $stateParams.workflowLatestRun;
    $stateParams.workflowLatestRun = null;
    $location.search('workflowLatestRun', null)

    vm.model = {
        appId: applicationId,
        entityId: entityId,
        activityId: activityId,
        childFilter: {'EFFECTOR': true, 'SUB-TASK': false},
        accordion: {summaryOpen: true, subTaskOpen: true, streamsOpen: true, workflowOpen: true},
        activity: {},
        workflow: {},
    };

    vm.modalTemplate = modalTemplate;
    vm.wideKilt = false;
    vm.toggleOldWorkflowRunStepDetails = () => { $scope.showOldWorkflowRunStepDetails = !$scope.showOldWorkflowRunStepDetails; }

    $scope.actions = {};

    let observers = [];

    if ($state.current.name === detailState.name) {

        function onActivityOrWorkflowUpdate() {
            delete $scope.actions['cancel'];
            delete $scope.actions['delete'];

            if (!vm.model.activity.endTimeUtc || vm.model.activity.endTimeUtc<=0) {
                $scope.actions.cancel = { label: 'Cancel task', doAction: () => { activityApi.cancelActivity(activityId); } };
            } else if (vm.model.workflow.data && vm.model.workflow.data.taskId && vm.model.workflow.data.status === 'RUNNING') {
                $scope.actions.cancel = { label: 'Cancel workflow', doAction: () => { activityApi.cancelActivity(vm.model.workflow.taskId); } };
            } else if (vm.model.workflow.data && vm.model.workflow.tag) {
                $scope.actions.delete = { label: 'Delete workflow', doAction: () => {
                    entityApi.deleteWorkflow(vm.model.workflow.tag.applicationId || applicationId, vm.model.workflow.tag.entityId || entityId, $scope.workflowId)
                        .then(result => $state.go($state.current, {}, {reload: true}) );
                } };
            }

            if (vm.model.activity.result!=undefined) {
                vm.model.activity.resultYaml = vm.yaml(vm.model.activity.result);
                const lines = vm.model.activity.resultYaml.split('\n');
                vm.model.activity.resultLineCount = lines.length;
                vm.model.activity.resultLineMaxLen = Math.max(...lines.map(x => x.length));
            }
        }

        function loadWorkflow(workflowTag, opts) {
            if (!opts) opts = {};
            if (!workflowTag) {
                workflowTag = {}
                opts.optimistic = true;
            }
            const optimistic = opts.optimistic;

            vm.model.workflow.loading = 'loading';

            $scope.workflowId = workflowTag.workflowId || $scope.workflowId || activityId;
            return entityApi.getWorkflow(workflowTag.applicationId || applicationId, workflowTag.entityId || entityId, $scope.workflowId).then(wResponse => {
                $scope.workflowId = wResponse.data.workflowId;
                workflowTag = {applicationId, entityId, workflowId: $scope.workflowId, ...workflowTag};
                if (optimistic) {
                    vm.model.workflow.tag = workflowTag;
                }
                vm.model.workflow.data = wResponse.data;
                vm.model.workflow.loading = 'loaded';
                vm.model.workflow.applicationId = workflowTag.applicationId;
                vm.model.workflow.entityId = workflowTag.entityId;

                if (opts.nonTask) {
                    const wft = (vm.model.workflow.data.replays || []).find(t => t.taskId === activityId);
                    if (wft) {
                        vm.model.activity = makeTaskStubFromWorkflowRecord(vm.model.workflow.data, wft);
                        vm.model.workflow.tag = getTaskWorkflowTag(vm.model.activity);
                    } else {
                        throw "Workflow task " + activityId + " not stored on workflow";
                    }

                    // give a better error
                    vm.error = $sce.trustAsHtml('Limited information on workflow task <b>' + _.escape(activityId) + '</b>.<br/><br/>' +
                        (!vm.model.activity.endTimeUtc || vm.model.activity.endTimeUtc == -1
                            ? "The run appears to have been interrupted, either by a server restart or a failure or cancellation and removal from memory."
                            : 'The workflow is known but this task is no longer stored in memory.'));
                }

                function processWorkflowData(wResponse2) {
                    // change the workflow object so widgets get refreshed
                    vm.model.workflow = { ...vm.model.workflow, data: wResponse2.data };

                    vm.model.workflow.isError = !!(vm.model.workflow.data.status && vm.model.workflow.data.status.startsWith("ERROR"));

                    const replays = (vm.model.workflow.data.replays || []);

                    vm.model.workflow.runMultipleTimes = replays.length > 1;
                    let workflowReplayId = activityId;
                    if (!replays.find(r => r.taskId === workflowReplayId)) {
                        let submittedById = ((vm.model.activity.submittedByTask || {}).metadata || {}).id;
                        if (replays.find(r => r.taskId === submittedById)) workflowReplayId = submittedById;
                        else workflowReplayId = null;
                    }
                    if (workflowReplayId) {
                        vm.model.workflow.runReplayId = workflowReplayId;
                        vm.model.workflow.runIsLatest = workflowReplayId == (replays[replays.length - 1] || {}).taskId;
                        vm.model.workflow.runIsOld = !vm.model.workflow.runIsLatest;
                    }
                    if (vm.model.workflow.runIsOld && vm.redirectToWorkflowLatestRun) {
                        vm.redirectToWorkflowLatestRun = false;
                        $state.go('main.inspect.activities.detail', {
                            applicationId: applicationId,
                            entityId: entityId,
                            activityId: (replays[replays.length - 1] || {}).taskId,
                        });
                    }

                    let osi = vm.model.workflow.data.oldStepInfo;
                    vm.model.workflow.finishedWithNoSteps = ((osi["-2"] || {}).previous || [])[0] == -1;

                    $scope.actions.workflowReplays = [];
                    if (vm.model.workflow.data.status !== 'RUNNING') {

                        $scope.actions.workflowReplays = [];
                        const stepIndex = (vm.model.workflow.tag || {}).stepIndex;  // selected by user
                        const currentStepIndex = vm.model.workflow.data.currentStepIndex;  // of workflow

                        let replayableDisabled = vm.model.workflow.data.replayableDisabled;
                        let replayableFromStart = vm.model.workflow.data.replayableFromStart && !replayableDisabled,
                            replayableFromLastStep = vm.model.workflow.data.replayableLastStep>=0 && !replayableDisabled;

                        if (replayableFromLastStep) {
                            let msg = 'Replay from last replay point (step '+(vm.model.workflow.data.replayableLastStep+1)+')';
                            $scope.actions.workflowReplays.push({ targetId: 'last', reason: msg+' from UI', label: msg });
                        }

                        // get current step, replay from that step
                        if (stepIndex>=0) {
                            const osi = vm.model.workflow.data.oldStepInfo[stepIndex] || {};
                            if (osi.replayableFromHere && !replayableDisabled) {
                                $scope.actions.workflowReplays.push({ targetId: ''+stepIndex, reason: 'Replay from step '+(stepIndex+1)+' from UI',
                                    label: 'Replay from here (step '+(stepIndex+1)+')' });
                            } else {
                                $scope.actions.workflowReplays.push({ targetId: ''+stepIndex, reason: 'Force replay from step '+(stepIndex+1)+' from UI',
                                    label: 'Force replay from here (step '+(stepIndex+1)+')', force: true });
                            }
                        }

                        if (replayableFromStart) {
                            let w1 = 'Replay from start', w2 = '(no other replay points)';
                            if (stepIndex<0 || (_.isNil(stepIndex) && vm.model.workflow.data.replayableLastStep==-2)) { w1 = 'Run'; w2 = 'again'; }
                            else if (replayableFromLastStep) w2 = '';
                            else if (_.isNil(stepIndex)) { w2 = '(did not start)'; }

                            $scope.actions.workflowReplays.push({targetId: 'start', reason: 'Replay from start from UI',
                                label: w1+' '+w2});
                        }

                        if (currentStepIndex>=0 && currentStepIndex < vm.model.workflow.data.stepsDefinition.length) {
                            let msg = 'eplay resuming (at step ' + (currentStepIndex + 1);
                            if (!replayableDisabled) {
                                $scope.actions.workflowReplays.push({ targetId: 'last', label: 'R'+msg+' if possible)', reason: 'R'+msg+') from UI' });
                            }
                            $scope.actions.workflowReplays.push({ targetId: 'last', label: 'Force r'+msg+')', reason: 'Force r'+msg+') from UI', force: true });
                        }

                        if (!replayableFromStart) {
                            $scope.actions.workflowReplays.push({targetId: 'start', reason: 'Force replay from start from UI',
                                label: 'Force replay from start', force: true});
                        }

                        // force replays
                        $scope.actions.workflowReplays.forEach(r => {
                            // could prompt for a reason
                            r.action = () => {
                                const opts = {};
                                opts.reason = r.reason;
                                if (r.force) opts.force = true;
                                entityApi.replayWorkflow(applicationId, entityId, $scope.workflowId, r.targetId, opts)
                                    .then(response => {
                                        console.log("Replay requested", response);
                                        $state.go('main.inspect.activities.detail', {
                                            applicationId: applicationId,
                                            entityId: entityId,
                                            activityId: response.data.id,
                                        });
                                    }).catch(error => {
                                        console.log("Replay failed", error);
                                    });
                            };
                        });
                    }
                    if (!$scope.actions.workflowReplays.length) delete $scope.actions['workflowReplays'];

                    onActivityOrWorkflowUpdate();
                }

                processWorkflowData(wResponse);

                if (vm.model.workflow.data.status === 'RUNNING') wResponse.interval(1000);
                observers.push(wResponse.subscribe(processWorkflowData, error => {
                    console.debug("Workflow no longer available, likely completed with retention 0. Removing from view.", error);
                    vm.model.workflow = {};
                }));

                function initFromWorkflowFirstReplayTask(task) {
                    if (task) {
                        const workflowYaml = (task.tags || []).find(t => t.workflow_yaml);
                        if (workflowYaml) {
                            $scope.workflow_yaml = workflowYaml.workflow_yaml;
                        }
                    }
                }

                if ($scope.workflowId === activityId) initFromWorkflowFirstReplayTask(vm.model.activity);
                else activityApi.activity($scope.workflowId).then((response)=> {
                    initFromWorkflowFirstReplayTask(response.data);
                });


            }).catch(error => {
                if (optimistic) {
                    vm.model.workflow.loading = null;
                    throw error;
                }
                console.log("Unable to load workflow", $scope.workflowId, error);

                vm.model.workflow.loading = 'error';
            });
        };

        activityApi.activity(activityId).then((response)=> {
            vm.model.activity = response.data;

            initializeBreadcrumbs(response.data);

            delete $scope.actions['effector'];
            delete $scope.actions['invokeAgain'];
            if ((vm.model.activity.tags || []).find(t => t=="EFFECTOR")) {
                const effectorName = (vm.model.activity.tags.find(t => t.effectorName) || {}).effectorName;
                const effectorParams = (vm.model.activity.tags.find(t => t.effectorParams) || {}).effectorParams;
                if (effectorName) {
                    $scope.actions.effector = {effectorName};
                    if (effectorParams) {
                        $scope.actions.invokeAgain = {effectorName, effectorParams, doAction: () => vm.invokeEffector(effectorName, effectorParams) };
                    }
                }
            }

            $scope.workflowId = null;  // if the task loads, force the workflow id to be found on it, otherwise ignore it
            if ((vm.model.activity.tags || []).find(t => t=="WORKFLOW")) {
                const workflowTag = getTaskWorkflowTag(vm.model.activity);
                if (workflowTag) {
                    vm.model.workflow.tag = workflowTag;
                    loadWorkflow(workflowTag);
                }
                const workflowYaml = vm.model.activity.tags.find(t => t.workflow_yaml);
                if (workflowYaml) {
                    $scope.workflow_yaml = workflowYaml.workflow_yaml;
                }
            }

            function saveActivity(response) {
                vm.model.activity = response.data;
                onActivityOrWorkflowUpdate();
                vm.error = undefined;
                vm.errorBasic = false;
            }

            saveActivity(response);

            if (!vm.model.activity.endTimeUtc || vm.model.activity.endTimeUtc<0) response.interval(1000);
            observers.push(response.subscribe(saveActivity));

        }).catch((error)=> {
            $log.warn('Error loading activity for '+activityId, error);
            // prefer this simpler error message over the specific ones below
            vm.errorBasic = true;
            vm.error = $sce.trustAsHtml('Cannot load task with ID: <b>' + _.escape(activityId) + '</b> <br/><br/>' +
                'The task is no longer stored in memory. Details may be available in logs.');

            // in case it corresponds to a workflow and not a task, try loading as a workflow
            loadWorkflow({workflowId: activityId}, { nonTask: true })
                .catch(error => {
                    loadWorkflow(null, { nonTask: true })
                        .catch(error => {
                            $log.debug("ID "+activityId+"/"+$scope.workflowId+" does not correspond to workflow either", error);
                        });
                });
        });

        function onActivityLoadUpdate() {
            vm.model.activityChildrenAndDeep = [];
            let seen = {};
            if (vm.model.activityChildren) {
                vm.model.activityChildren.forEach(t => {
                    vm.model.activityChildrenAndDeep.push(t);
                    seen[t.id] = true;
                });
            }
            if (vm.model.activitiesDeep) {
                Object.values(vm.model.activitiesDeep).forEach(t => {
                    if (!seen[t.id]) {
                        vm.model.activityChildrenAndDeep.push(t);
                        seen[t.id] = true;
                    }
                });
            }
        }

        $scope.breadcrumbsLoading = true;
        $scope.breadcrumbs = [];
        $scope.breadcrumbsExpanded = false;
        function initializeBreadcrumbs(activity) {
            $scope.breadcrumbs.unshift(activity);
            if (activity.submittedByTask) {
                activityApi.activity(activity.submittedByTask.metadata.id).then(response => {
                    initializeBreadcrumbs(response.data);
                }).catch(e => {
                    console.warn("Error loading breadcrumbs", e);
                    $scope.breadcrumbsLoading = false;
                });
            } else {
                $scope.breadcrumbsLoading = false;
            }
        }
        vm.expandBreadcrumbs = () => {
            $scope.breadcrumbsExpanded = true;
        }

        activityApi.activityChildren(activityId).then((response)=> {
            vm.model.activityChildren = processActivityChildren(response.data);
            vm.error = undefined;
            onActivityLoadUpdate();

            // could improve by making just one call for children+deep, or combining the results;
            // but for now just read them both frequently
            if (!vm.model.activity.endTimeUtc || vm.model.activity.endTimeUtc<0) response.interval(1000);
            observers.push(response.subscribe((response)=> {
                vm.model.activityChildren = processActivityChildren(response.data);
                if (!vm.errorBasic) {
                    vm.error = undefined;
                }
                onActivityLoadUpdate();
            }));
        }).catch((error)=> {
            $log.warn('Error loading activity children  for '+activityId, error);
            if (!vm.errorBasic) {
                vm.error = 'Cannot load activity children for activity ID: ' + activityId;
            }
        });
        
        activityApi.activityDescendants(activityId, 8, true).then((response)=> {
            vm.model.activitiesDeep = response.data;
            vm.error = undefined;
            onActivityLoadUpdate();

            if (!vm.model.activity.endTimeUtc || vm.model.activity.endTimeUtc<0) response.interval(1000);
            observers.push(response.subscribe((response)=> {
                vm.model.activitiesDeep = response.data;
                if (!vm.errorBasic) {
                    vm.error = undefined;
                }
                onActivityLoadUpdate();
            }));
        }).catch((error)=> {
            $log.warn('Error loading activity children deep for '+activityId, error);
            if (!vm.errorBasic) {
                vm.error = 'Cannot load activities children deep for activity ID: ' + activityId;
            }
        });
        
    }

    vm.isNonEmpty = Utils.isNonEmpty;
    vm.yaml = (o) => typeof o === 'string' ? o : jsyaml.dump(o);

    vm.openInRunModel = function (workflowYaml) {
        $uibModal.open({
            animation: true,
            template: runWorkflowModalTemplate,
            controller: ['$scope', '$http', '$uibModalInstance', 'serverApi', 'applicationId', 'entityId', 'workflowYaml', runWorkflowController],
            size: 'lg',
            resolve: {
                applicationId: ()=>(applicationId),
                entityId: ()=>(entityId),
                workflowYaml: ()=>(workflowYaml),
            }
        }).result.then((closeData)=> {
            $state.go('main.inspect.activities.detail', {
                applicationId: applicationId,
                entityId: closeData.entityId,
                activityId: closeData.id
            });
        });
    }

    vm.getStreamIdsInOrder = function () {
        // sort with known streams first, in preferred order
        // also return just the IDs, setting a map
        var knownMap = {env: null, stdin: null, stdout: null, stderr: null};
        var otherMap = {};
        for (let [name, s] of Object.entries(vm.model.activity.streams)) {
            if (name in knownMap) {
                knownMap[name] = s;
            } else {
                otherMap[name] = s;
            }
        }

        // Do not display streams that are not initialized
        for (let name in knownMap) {
            if (knownMap[name] === null || knownMap[name] === undefined) {
                delete knownMap[name];
            }
        }

        $scope.streamsById = Object.assign({}, knownMap, otherMap);
        return Object.keys($scope.streamsById);
    };

    vm.setWideKilt = function (newValue) {
        vm.wideKilt = newValue;
        // empirically delay of 100ms means it runs after the resize;
        // seems there is no way to hook in to resize events so it is
        // either this or a $scope.$watch with very low interval
        $timeout(function() { $scope.$broadcast('resize') }, 100);
    };

    vm.stringify = (data) => JSON.stringify(data, null, 2);
    vm.stringifiedSize = (data) => JSON.stringify(data).length;

    vm.invokeEffector = (effectorName, effectorParams) => {
        entityApi.invokeEntityEffector(applicationId, entityId, effectorName, effectorParams).then((response) => {
            $state.go('main.inspect.activities.detail', {
                applicationId: applicationId,
                entityId: entityId,
                activityId: response.data.id,
            });
        });
    }

    $scope.$on('$destroy', ()=> {
        observers.forEach((observer)=> {
            observer.unsubscribe();
        });
    });

    function processActivityChildren(data) {
        return data.map((child)=> {
            if (child.submittedByTask && child.submittedByTask.metadata.id === activityId && child.tags.indexOf('SUB-TASK') === -1) {
                child.tags.push("BACKGROUND-TASK");
            }
            return child;
        });
    }

    vm.onFilteredActivitiesChange = function (newActivities, globalFilters) {
        // this uses activity descendants api method which only uses TaskChildren,
        // so transient tasks etc less relevant
    }

    vm.showReplayHelp = () => {
        $scope.showReplayHelp = !$scope.showReplayHelp;
    }

    vm.isNullish = _.isNil;
    vm.isEmpty = x => vm.isNullish(x) || (x.length==0) || (typeof x === 'object' && !Object.keys(x).length);
    vm.isNonEmpty = x => !vm.isEmpty(x);
}

export function getTaskWorkflowTag(task) {
    if (!task) return null;
    if (!task.tags) return null;
    return task.tags.find(t => t.workflowId);
}
