/* Licensed 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.
 */
'use strict';

angular.module('flowableApp')
    .controller('ProcessesController', ['$rootScope', '$scope', '$translate', '$http', '$timeout', '$location', '$modal', '$routeParams', '$popover', 'appResourceRoot', 'AppDefinitionService', 'ProcessService',
        function ($rootScope, $scope, $translate, $http, $timeout, $location, $modal, $routeParams, $popover, appResourceRoot, AppDefinitionService, ProcessService) {

        var processId = $routeParams.processId;

        // Ensure correct main page is set
        $rootScope.setMainPageById('processes');

        // Initialize model
        $scope.model = {
            page: 0,
            initialLoad: false,
            mode: 'process-list'
        };

        $scope.model.runtimeSorts = [
            { 'id': 'created-desc', 'title': 'PROCESS.FILTER.CREATED-DESC'},
            { 'id': 'created-asc', 'title': 'PROCESS.FILTER.CREATED-ASC' }
        ];

        $scope.model.completedSorts = [];
        $scope.model.completedSorts.push($scope.model.runtimeSorts[0]); // needs to be same reference!
        $scope.model.completedSorts.push($scope.model.runtimeSorts[1]); // needs to be same reference!
        $scope.model.completedSorts.push({ 'id': 'ended-asc', 'title': 'PROCESS.FILTER.ENDED-DESC' });
        $scope.model.completedSorts.push({ 'id': 'ended-desc', 'title': 'PROCESS.FILTER.ENDED-ASC' });

        $scope.model.sorts = $scope.model.runtimeSorts;

        $scope.model.stateFilterOptions = [
            { 'id': 'running', 'title': 'PROCESS.FILTER.STATE-RUNNING' },
            { 'id': 'completed', 'title': 'PROCESS.FILTER.STATE-COMPLETED' },
            { 'id': 'all', 'title': 'PROCESS.FILTER.STATE-ALL' }
        ];

        $scope.model.filter = {
            loading: false,
            expanded: false,
            param: {
                state: $scope.model.stateFilterOptions[0],
                sort: $scope.model.sorts[0].id
            }
        };

        $scope.appDefinitionKey = $routeParams.appDefinitionKey;
        $scope.missingAppdefinition = $scope.appDefinitionKey === false;

        // In case of viewing process instances in an app-context, need to make filter aware of this
        $scope.model.filter.param.appDefinitionKey = $scope.appDefinitionKey;

        // The filter is stored on the rootScope, which allows the user to switch back and forth without losing the filter.
        if ($rootScope.processFilter !== null && $rootScope.processFilter !== undefined) {
            $scope.model.filter.param = $rootScope.processFilter.param;
        } else {
            $rootScope.processFilter = { param: $scope.model.filter.param }
        }

        // Update app on rootScope. If app id present, it will fetch definition if not already fetched to update view and navigation accordingly
        AppDefinitionService.setActiveAppDefinitionKey($scope.appDefinitionKey);

        $scope.selectProcessInstance = function (processInstance) {
            $scope.selectedProcessInstance = processInstance;
            $scope.state = {noProcesses:false};
        };

        $scope.expandFilter = function () {
            $scope.model.filter.expanded = true;
        };

        $scope.collapseFilter = function () {
            $scope.model.filter.expanded = false;
        };

        $scope.$watch("model.filter.param", function (newValue) {
            if (newValue) {
                if ($scope.model.initialLoad) {
                    $scope.loadProcessInstances();
                }

                if (newValue.state.id === 'completed' || newValue.state.id === 'all') {
                    $scope.model.sorts = $scope.model.completedSorts;
                } else {
                    $scope.model.sorts = $scope.model.runtimeSorts;
                    if (newValue.sort === 'ended-asc' || newValue.sort === 'ended-desc') {
                        $scope.model.filter.param.sort = $scope.model.sorts[0].id;
                    }
                }
            }
        }, true);

        $scope.nextPage = function () {
            $scope.loadProcessInstances(true);
        };

        // TODO: move to service
        $scope.loadProcessInstances = function (nextPage) {

            $scope.model.filter.loading = true;

            var params = $scope.model.filter.param;

            if (nextPage) {
                $scope.model.page += 1;
            } else {
                $scope.model.page = 0;
            }

            var instanceQueryData = {
                sort: params.sort,
                page: $scope.model.page
            };

            if (params.appDefinitionKey) {
                instanceQueryData.appDefinitionKey = params.appDefinitionKey;
            }

            if (params.state) {
                instanceQueryData.state = params.state.id;
            }


            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/query/process-instances', data: instanceQueryData}).
                success(function (response, status, headers, config) {
                    $scope.model.initialLoad = true;
                    var instances = response.data;

                    if (response.start > 0) {
                        // Add results instead of removing existing ones
                        for (var i = 0; i < instances.length; i++) {
                            $scope.model.processInstances.push(instances[i]);
                        }

                        $scope.state = {noProcesses: false};
                    } else {
                        $scope.model.processInstances = instances;
                        $scope.state = {noProcesses: (!response.data || response.data.length == 0)};
                    }

                    if (response.start + response.size < response.total) {
                        // More pages available
                        $scope.model.hasNextPage = true;
                    } else {
                        $scope.model.hasNextPage = false;
                    }

                    var isSelected = false;

                    if ($rootScope.root.selectedProcessId) {
                        for (var i = 0; i < instances.length; i++) {
                            if (instances[i].id == $rootScope.root.selectedProcessId) {
                                isSelected = true;
                                $scope.selectedProcessInstance = instances[i];
                                break;
                            }
                        }
                        $rootScope.root.selectedProcessId = undefined;
                    }
                    if (!isSelected && instances.length > 0) {
                        if (!$scope.selectedProcessInstance) {
                            $scope.selectedProcessInstance = instances[0];
                        }
                    }

                    // If there is a new process instance, we want it to be selected
                    if ($scope.newProcessInstance !== null && $scope.newProcessInstance !== undefined) {
                        if ($scope.newProcessInstance.id !== null && $scope.newProcessInstance.id !== undefined) {
                            for (var instanceIndex = 0; instanceIndex < $scope.model.processInstances.length; instanceIndex++) {
                                if ($scope.model.processInstances[instanceIndex].id === $scope.newProcessInstance.id) {
                                    $scope.selectedProcessInstance = $scope.model.processInstances[instanceIndex];
                                    break;
                                }
                            }
                        }
                       // Always reset when loading process instance
                        $scope.newProcessInstance = undefined;
                    }

                    $scope.model.filter.loading = false;
                    $rootScope.window.forceRefresh = true;
                }).
                error(function (response, status, headers, config) {
                    console.log('Something went wrong: ' + response);
                });
        };

        $scope.selectProcessDefinition = function (definition) {
            $scope.newProcessInstance.processDefinitionId = definition.id;
            $scope.newProcessInstance.name = definition.name + ' - ' + new moment().format('MMMM Do YYYY');
            $scope.newProcessInstance.processDefinition = definition;

            $timeout(function () {
                angular.element('#start-process-name').focus();
            }, 20);
        };

        $scope.selectStateFilter = function (state) {
            if (state != $scope.model.filter.param.state) {
                $scope.model.filter.param.state = state;
                $scope.collapseFilter();
                $scope.selectedProcessInstance = undefined;
            }
        };

        $scope.sortChanged = function() {
            $scope.selectedProcessInstance = undefined;
        };

        $scope.selectDefaultDefinition = function() {
            // Select first non-default definition, if any
            ProcessService.getProcessDefinitions($scope.appDefinitionKey).then(function(response) {
            	$rootScope.root.processDefinitions = response.data;
	            if ($scope.root.processDefinitions && $scope.root.processDefinitions.length > 0) {
	                for (var i=0; i< $scope.root.processDefinitions.length; i++) {
	                    var def = $scope.root.processDefinitions[i];
	                    if (def.id != 'default') {
	                        $scope.selectProcessDefinition(def);
	                        break;
	                    }
	                }
	            }
	        });

        };

        $scope.backToList = function(reloadProcessInstances) {

            $scope.newProcessInstance = undefined;

            $scope.model.mode = 'process-list';
            $scope.startFormError = undefined;

            // If param is true: reload, no questions asked
            if (reloadProcessInstances) {

                // Reset selection
                $scope.selectedProcessInstance = undefined;

                // Reset filters
                $scope.model.filter.param.state = $scope.model.stateFilterOptions[0];
                $scope.model.filter.param.sort = $scope.model.sorts[0].id;

                $scope.loadProcessInstances();
            }

            // In case we're coming from the task page, no process instances have been loaded
            if ($scope.model.processInstances === null || $scope.model.processInstances === undefined) {
                $scope.loadProcessInstances();
            }

        };

        $scope.createProcessInstance = function () {

            // Reset state
            $rootScope.root.showStartForm = false;

            $scope.model.mode = 'process-create';
            $scope.newProcessInstance = {};
            $scope.selectDefaultDefinition();
        };

        $scope.$on('process-started-error', function (event, data) {
            $rootScope.addAlert(data.error.message, 'error');
        });

        // Called after form is submitted
        $scope.$on('process-started', function (event, data) {
            $scope.newProcessInstance.id = data.id;
            $scope.backToList(true);
        });

        $scope.startProcessInstanceWithoutForm = function() {
            $scope.newProcessInstance.loading = true;
            var createInstanceData = {processDefinitionId: $scope.newProcessInstance.processDefinition.id, name: $scope.newProcessInstance.name};
            $http({method: 'POST', url: FLOWABLE.CONFIG.contextRoot + '/app/rest/process-instances', data: createInstanceData}).
                success(function (response, status, headers, config) {
                    $scope.newProcessInstance.id = response.id;
                    $scope.newProcessInstance.loading = false;
                    $scope.backToList(true);

                }).
                error(function (response, status, headers, config) {
                    $scope.newProcessInstance.loading = false;

                    if(response && response.messageKey) {
                        $translate(response.messageKey, response.customData).then(function(message) {
                            $scope.errorMessage = message;
                            console.log(message);
                        });
                    }
                });
        };

        $rootScope.loadProcessDefinitions($scope.appDefinitionKey);

        // If 'createProcessInstance' is set (eg from the task page)
        if ($rootScope.createProcessInstance) {
            $rootScope.createProcessInstance = false;
            $scope.createProcessInstance();
        } else {
            $scope.loadProcessInstances();
        }

    }]);
