/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-management-plugin
 * ==========
 * Copyright (C) 2020 - 2023 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
var Entaxy;
(function (Entaxy) {
    Entaxy._module
    .component('entaxyAllConnectorsTable', {
        template:
        `
          <h2>
            Connectors
          </h2>

          <pf-toolbar class="entaxy-toolbar" config="$ctrl.toolbarConfig"></pf-toolbar>
          <pf-table-view config="$ctrl.tableConfig"
                          columns="$ctrl.tableColumns"
                          action-buttons="$ctrl.tableActionButtons"
                          menu-actions="$ctrl.menuActions"
                          page-config="$ctrl.pageConfig"
                          items="$ctrl.viewedItems">
          </pf-table-view>

        `,
        controller: EntaxyAllConnectorsTableController
    })
    .name;

    function EntaxyAllConnectorsTableController($q, workspace, $scope, operationsService, jolokia, jolokiaService, entaxyService, entaxyLegacyConnectorService) {
        'ngInject';

        let ctrl = this;
        ctrl.workspace = workspace;

        ctrl.itemName = "Connector";
        ctrl.statusName = "BundleState";

        let filterValues = Entaxy.getAllBundleStates();

        ctrl.tableConfig = {
            selectionMatchProp: 'displayName',
            showCheckboxes: false
        };

        ctrl.toolbarConfig = {
            filterConfig: {
                fields: [
                    {
                        id: 'direction',
                        title: 'Direction',
                        placeholder: 'Filter by Direction...',
                        filterType: 'select',
                        filterValues: ['in', 'out']
                    },
                    {
                        id: 'displayName',
                        title: 'Name',
                        placeholder: 'Filter by Name...',
                        filterType: 'text'
                    },
                    {
                        id: 'profile',
                        title: 'Profile',
                        placeholder: 'Filter by Profile...',
                        filterType: 'select',
                        filterValues: getProfiles().map(profile => profile.name)
                    },
                    {
                        id: 'status',
                        title: 'Status',
                        placeholder: 'Filter by Status...',
                        filterType: 'select',
                        filterValues: filterValues
                    }
                ],
                appliedFilters: [],
                onFilterChange: filterChange
            },
            isTableView: true
        };

        ctrl.tableColumns = [
            { header: 'Direction', itemField: 'direction' },
            { header: 'Name', itemField: 'displayName' },
            { header: 'Profile', itemField: 'profile' },
            { header: 'Status', itemField: 'status' }
        ];

        ctrl.pageConfig = Entaxy.getStandardPageConfig();

        function filterChange(filters) {
            ctrl.viewedItems = Entaxy.applyFilters(ctrl.items, filters, matchesFilter);
            ctrl.toolbarConfig.filterConfig.resultsCount = ctrl.viewedItems.length;
        };

        function matchesFilter(item, filter) {
            let match = true;
            if (filter.id === 'direction') {
                match = item.direction === filter.value;
            } else if (filter.id === 'displayName') {
                match = item.displayName.match(filter.value) !== null;
            } else if (filter.id === 'profile') {
                match = item.profile === filter.value;
            } else if (filter.id === 'status') {
                match = item.status === filter.value;
            }
            return match;
        };

        ctrl.items = [];
        ctrl.viewedItems = [];

        ctrl.$onInit = function() {
            populateTable();

            let primaryActions = [
                {
                    name: 'Add Connector',
                    actionFn: () => ctrl.showModal(Entaxy.MODAL_MODES.ADD),
                    isDisabled: getProfiles().length === 0
                },
                {
                    name: 'Add Legacy Connector',
                    actionFn: () => ctrl.showAddLegacyConnectorModal(),
                    isDisabled: getProfiles().length === 0
                }
            ];

            ctrl.toolbarConfig.actionsConfig = {
                primaryActions: primaryActions
            };

            ctrl.tableActionButtons = [
                { name: 'Start', title: 'Start ' + ctrl.itemName, actionFn: startItem },
                { name: 'Stop', title: 'Stop ' + ctrl.itemName, actionFn: stopItem },
                { name: 'Uninstall', title: 'Uninstall ' + ctrl.itemName, actionFn: uninstallItem }
            ];

            ctrl.menuActions = [
                { name: 'View Properties', title: 'View ' + ctrl.itemName + ' Properties', actionFn: showPropertiesModal },
                { name: 'Edit Properties', title: 'Edit ' + ctrl.itemName + ' Properties', actionFn: showPropertiesModal }
            ];
        }

        function showPropertiesModal(action, item) {
            if (action.name === 'View Properties') {
                ctrl.showModal(Entaxy.MODAL_MODES.VIEW, item);
            } else if (action.name === 'Edit Properties') {
                ctrl.showModal(Entaxy.MODAL_MODES.EDIT, item);
            }
        }

        function populateTable() {
            let items = [];
            let promises = [];

            let profilesFolder = entaxyService.getDomainFolder()
                .findDescendant(child => child.objectName && child.objectName.endsWith('category=profiles'));

            let mbeans = entaxyService.getAllChildMBeansByRuntimeType(profilesFolder, 'entaxy.runtime.connector');

            mbeans.forEach(mbean => {
                let profileMBeanName = findConnectorParentProfileMBeanName(mbean);

                promises.push(jolokiaService.getAttributes(mbean.objectName, [ctrl.statusName, 'Name', 'DisplayName', 'Direction'])
                .then((response) => {
                    items.push({
                        name: response['Name'],
                        displayName: response['DisplayName'] === '' || response['DisplayName'].startsWith('ERROR') ? response['Name'] : response['DisplayName'],
                        direction: response['Direction'] === '' || response['Direction'].startsWith('ERROR') ? '-' : response['Direction'],
                        status: response[ctrl.statusName],
                        mbeanName: mbean.objectName,
                        profileMBeanName: profileMBeanName,
                        profile: jolokia.getAttribute(profileMBeanName, 'Name')
                    });
                }));
            });

            $q.all(promises)
            .then(() => {
                ctrl.items = items;
                ctrl.viewedItems = items;

                let filters = ctrl.toolbarConfig.filterConfig.appliedFilters;
                if (filters.length > 0) {
                    filterChange(filters);
                } else {
                    ctrl.toolbarConfig.filterConfig.resultsCount = items.length;
                }
            });
        }

        function findConnectorParentProfileMBeanName(connectorMBean) {
            let parent = connectorMBean.parent;
            if (parent.objectName) {
                let attributes = jolokia.getAttribute(parent.objectName);
                if (attributes.RuntimeType === 'entaxy.runtime.profile') {
                    return parent.objectName;
                }
            } else {
                return findConnectorParentProfileMBeanName(parent);
            }
        }

        function getProfiles() {
            let profilesFolder = entaxyService.getDomainFolder()
                .findDescendant(child => child.objectName && child.objectName.endsWith('category=profiles'));
            let profileMbeans = entaxyService.getAllChildMBeansByRuntimeType(profilesFolder, 'entaxy.runtime.profile');
            let profiles = profileMbeans.length > 0 ?
                profileMbeans.map(mbean => {
                    let name = jolokia.getAttribute(mbean.objectName, 'Name');
                    return {
                        name: name,
                        displayName: name,
                        mbeanName: mbean.objectName
                    };
                }) : [];
            return profiles;
        }

        ctrl.showModal = function(mode, item) {

            if (mode === Entaxy.MODAL_MODES.ADD) {

                let resolve = {
                    mode: () => mode,
                    itemType: () => ctrl.itemName,
                    profiles: () => getProfiles()
                };

                entaxyService.openAddItemModalAndProcessResults(resolve);
            } else {
                let mbeanName = item.profileMBeanName;
                entaxyService.openEditItemModalAndProcessResults(mbeanName, ctrl.itemName, item.name, mode);
            }
        }

        ctrl.showAddLegacyConnectorModal = function() {
            let resolve = {
                profiles: () => getProfiles()
            };

            entaxyLegacyConnectorService.openAddLegacyConnectorModal(resolve).then(connectorArgs => {
                addLegacyConnector(connectorArgs);
            });
        }

        function addLegacyConnector(connectorArgs) {

            let args = entaxyLegacyConnectorService.getArguments(connectorArgs);
            let mbeanName = connectorArgs.profile.mbeanName;

            operationsService.executeOperation(mbeanName, { name: 'addConnector' }, args)
            .then(result => {
                Core.notification('success', result, 3000);
            }).catch(error => {
                Core.notification('danger', error, 5000);
            });
        }

        $scope.$on(Jmx.TreeEvent.Updated, () => {
            populateTable();
        });

        function startItem(action, item) {
            if (item.status !== 'Active') {
                processOperation(item.profileMBeanName, 'start', item.name);
            } else {
                Core.notification('info', ctrl.itemName + ' has been already started');
            }
        }

        function stopItem(action, item) {
            if (item.status !== 'Resolved') {
                processOperation(item.profileMBeanName, 'stop', item.name);
            } else {
                Core.notification('info', ctrl.itemName + ' has been already stopped');
            }
        }

        function uninstallItem(action, item) {
            let title = 'Confirm Uninstalling';
            let message = 'Do you want to uninstall ' + ctrl.itemName.toLowerCase() + ' ' + item.displayName + '?';

            entaxyService.openConfirmationWindow(title, message).then(() => {
                processOperation(item.profileMBeanName,'remove', item.name);
            });
        }

        function processOperation(mbeanName, operationName, selectedItemName) {
            let operation = { name: operationName + ctrl.itemName };
            entaxyService.processTableOperation(mbeanName, operation, selectedItemName);
        }

        ctrl.dismissAlert = () => ctrl.alert = null;

    }
    EntaxyAllConnectorsTableController.$inject = ['$q', 'workspace', '$scope', 'operationsService', 'jolokia', 'jolokiaService', 'entaxyService', 'entaxyLegacyConnectorService'];

})(Entaxy || (Entaxy = {}));
