/*
 * 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.
 */

/* global define, module, require, exports */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery',
                'Slick',
                'nf.Common',
                'nf.Dialog',
                'nf.ErrorHandler'],
            function ($, Slick, nfCommon, nfDialog, nfErrorHandler) {
                return (nf.TemplatesTable = factory($, Slick, nfCommon, nfDialog, nfErrorHandler));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.TemplatesTable =
            factory(require('jquery'),
                require('Slick'),
                require('nf.Common'),
                require('nf.Dialog'),
                require('nf.ErrorHandler')));
    } else {
        nf.TemplatesTable = factory(root.$,
            root.Slick,
            root.nf.Common,
            root.nf.Dialog,
            root.nf.ErrorHandler);
    }
}(this, function ($, Slick, nfCommon, nfDialog, nfErrorHandler) {
    'use strict';

    var isDisconnectionAcknowledged = false;

    /**
     * Configuration object used to hold a number of configuration items.
     */
    var config = {
        urls: {
            templates: '../nifi-api/flow/templates'
        }
    };

    /**
     * Sorts the specified data using the specified sort details.
     *
     * @param {object} sortDetails
     * @param {object} data
     */
    var sort = function (sortDetails, data) {
        // defines a function for sorting
        var comparer = function (a, b) {
            if (a.permissions.canRead && b.permissions.canRead) {
                if (sortDetails.columnId === 'timestamp') {
                    var aDate = nfCommon.parseDateTime(a.template[sortDetails.columnId]);
                    var bDate = nfCommon.parseDateTime(b.template[sortDetails.columnId]);
                    return aDate.getTime() - bDate.getTime();
                } else {
                    var aString = nfCommon.isDefinedAndNotNull(a.template[sortDetails.columnId]) ? a.template[sortDetails.columnId] : '';
                    var bString = nfCommon.isDefinedAndNotNull(b.template[sortDetails.columnId]) ? b.template[sortDetails.columnId] : '';
                    return aString === bString ? 0 : aString > bString ? 1 : -1;
                }
            } else {
                if (!a.permissions.canRead && !b.permissions.canRead) {
                    return 0;
                }
                if (a.permissions.canRead) {
                    return 1;
                } else {
                    return -1;
                }
            }
        };

        // perform the sort
        data.sort(comparer, sortDetails.sortAsc);
    };

    /**
     * Prompts the user before attempting to delete the specified template.
     *
     * @argument {object} templateEntity     The template
     */
    var promptToDeleteTemplate = function (templateEntity) {
        // prompt for deletion
        nfDialog.showYesNoDialog({
            headerText: 'Delete Template',
            dialogContent: 'Delete template \'' + nfCommon.escapeHtml(templateEntity.template.name) + '\'?',
            yesHandler: function () {
                deleteTemplate(templateEntity);
            }
        });
    };

    /**
     * Opens the access policies for the specified template.
     *
     * @param templateEntity
     */
    var openAccessPolicies = function (templateEntity) {
        // only attempt this if we're within a frame
        if (top !== window) {
            // and our parent has canvas utils and shell defined
            if (nfCommon.isDefinedAndNotNull(parent.nf) && nfCommon.isDefinedAndNotNull(parent.nf.PolicyManagement) && nfCommon.isDefinedAndNotNull(parent.nf.Shell)) {
                parent.nf.PolicyManagement.showTemplatePolicy(templateEntity);
                parent.$('#shell-close-button').click();
            }
        }
    };

    /**
     * Deletes the template with the specified id.
     *
     * @argument {string} templateEntity     The template
     */
    var deleteTemplate = function (templateEntity) {
        $.ajax({
            type: 'DELETE',
            url: templateEntity.template.uri + '?' + $.param({
                'disconnectedNodeAcknowledged': isDisconnectionAcknowledged
            }),
            dataType: 'json'
        }).done(function () {
            var templatesGrid = $('#templates-table').data('gridInstance');
            var templatesData = templatesGrid.getData();
            templatesData.deleteItem(templateEntity.id);

            // update the total number of templates
            $('#total-templates').text(templatesData.getItems().length);
        }).fail(nfErrorHandler.handleAjaxError);
    };

    /**
     * Get the text out of the filter field. If the filter field doesn't
     * have any text it will contain the text 'filter list' so this method
     * accounts for that.
     */
    var getFilterText = function () {
        return $('#templates-filter').val();
    };

    /**
     * Applies the filter found in the filter expression text field.
     */
    var applyFilter = function () {
        // get the dataview
        var templatesGrid = $('#templates-table').data('gridInstance');

        // ensure the grid has been initialized
        if (nfCommon.isDefinedAndNotNull(templatesGrid)) {
            var templatesData = templatesGrid.getData();

            // update the search criteria
            templatesData.setFilterArgs({
                searchString: getFilterText(),
                property: $('#templates-filter-type').combo('getSelectedOption').value
            });
            templatesData.refresh();
        }
    };

    /**
     * Performs the filtering.
     *
     * @param {object} item     The item subject to filtering
     * @param {object} args     Filter arguments
     * @returns {Boolean}       Whether or not to include the item
     */
    var filter = function (item, args) {
        if (args.searchString === '') {
            return true;
        }

        try {
            // perform the row filtering
            var filterExp = new RegExp(args.searchString, 'i');
        } catch (e) {
            // invalid regex
            return false;
        }

        // perform the filter
        return item.template[args.property].search(filterExp) >= 0;
    };

    /**
     * Downloads the specified template.
     *
     * @param {object} templateEntity     The template
     */
    var downloadTemplate = function (templateEntity) {
        window.open(templateEntity.template.uri + '/download');
    };

    return {
        /**
         * Initializes the templates list.
         */
        init: function (disconnectionAcknowledged) {
            isDisconnectionAcknowledged = disconnectionAcknowledged;

            // define the function for filtering the list
            $('#templates-filter').keyup(function () {
                applyFilter();
            });

            // filter type
            $('#templates-filter-type').combo({
                options: [{
                    text: 'by name',
                    value: 'name'
                }, {
                    text: 'by description',
                    value: 'description'
                }],
                select: function (option) {
                    applyFilter();
                }
            });

            var timestampFormatter = function (row, cell, value, columnDef, dataContext) {
                if (!dataContext.permissions.canRead) {
                    return '';
                }

                return nfCommon.escapeHtml(dataContext.template.timestamp);
            };

            var nameFormatter = function (row, cell, value, columnDef, dataContext) {
                if (!dataContext.permissions.canRead) {
                    return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
                }

                return nfCommon.escapeHtml(dataContext.template.name);
            };

            var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
                if (!dataContext.permissions.canRead) {
                    return '';
                }

                return nfCommon.formatValue(dataContext.template.description);
            };

            var groupIdFormatter = function (row, cell, value, columnDef, dataContext) {
                if (!dataContext.permissions.canRead) {
                    return '';
                }

                return nfCommon.escapeHtml(dataContext.template.groupId);
            };

            // function for formatting the actions column
            var actionFormatter = function (row, cell, value, columnDef, dataContext) {
                var markup = '';

                if (dataContext.permissions.canRead === true) {
                    markup += '<div title="Download" class="pointer export-template icon icon-template-save"></div>';
                }

                if (dataContext.permissions.canWrite === true) {
                    markup += '<div title="Remove Template" class="pointer prompt-to-delete-template fa fa-trash"></div>';
                }

                // allow policy configuration conditionally if framed
                if (top !== window && nfCommon.canAccessTenants()) {
                    if (nfCommon.isDefinedAndNotNull(parent.nf) && nfCommon.isDefinedAndNotNull(parent.nf.CanvasUtils) && parent.nf.CanvasUtils.isManagedAuthorizer()) {
                        markup += '<div title="Access Policies" class="pointer edit-access-policies fa fa-key"></div>';
                    }
                }

                return markup;
            };

            // initialize the templates table
            var templatesColumns = [
                {
                    id: 'timestamp',
                    name: 'Date/Time',
                    sortable: true,
                    defaultSortAsc: false,
                    resizable: false,
                    formatter: timestampFormatter,
                    width: 225,
                    maxWidth: 225
                },
                {
                    id: 'name',
                    name: 'Name',
                    sortable: true,
                    resizable: true,
                    formatter: nameFormatter
                },
                {
                    id: 'description',
                    name: 'Description',
                    sortable: true,
                    resizable: true,
                    formatter: descriptionFormatter
                },
                {
                    id: 'groupId',
                    name: 'Process Group Id',
                    sortable: true,
                    resizable: true,
                    formatter: groupIdFormatter
                },
                {
                    id: 'actions',
                    name: '&nbsp;',
                    sortable: false,
                    resizable: false,
                    formatter: actionFormatter,
                    width: 100,
                    maxWidth: 100
                }
            ];

            var templatesOptions = {
                forceFitColumns: true,
                enableTextSelectionOnCells: true,
                enableCellNavigation: false,
                enableColumnReorder: false,
                autoEdit: false,
                rowHeight: 24
            };

            // initialize the dataview
            var templatesData = new Slick.Data.DataView({
                inlineFilters: false
            });
            templatesData.setItems([]);
            templatesData.setFilterArgs({
                searchString: getFilterText(),
                property: $('#templates-filter-type').combo('getSelectedOption').value
            });
            templatesData.setFilter(filter);

            // initialize the sort
            sort({
                columnId: 'timestamp',
                sortAsc: false
            }, templatesData);

            // initialize the grid
            var templatesGrid = new Slick.Grid('#templates-table', templatesData, templatesColumns, templatesOptions);
            templatesGrid.setSelectionModel(new Slick.RowSelectionModel());
            templatesGrid.registerPlugin(new Slick.AutoTooltips());
            templatesGrid.setSortColumn('timestamp', false);
            templatesGrid.onSort.subscribe(function (e, args) {
                sort({
                    columnId: args.sortCol.id,
                    sortAsc: args.sortAsc
                }, templatesData);
            });

            // configure a click listener
            templatesGrid.onClick.subscribe(function (e, args) {
                var target = $(e.target);

                // get the node at this row
                var item = templatesData.getItem(args.row);

                // determine the desired action
                if (templatesGrid.getColumns()[args.cell].id === 'actions') {
                    if (target.hasClass('export-template')) {
                        downloadTemplate(item);
                    } else if (target.hasClass('prompt-to-delete-template')) {
                        promptToDeleteTemplate(item);
                    } else if (target.hasClass('edit-access-policies')) {
                        openAccessPolicies(item);
                    }
                }
            });

            // wire up the dataview to the grid
            templatesData.onRowCountChanged.subscribe(function (e, args) {
                templatesGrid.updateRowCount();
                templatesGrid.render();

                // update the total number of displayed processors
                $('#displayed-templates').text(args.current);
            });
            templatesData.onRowsChanged.subscribe(function (e, args) {
                templatesGrid.invalidateRows(args.rows);
                templatesGrid.render();
            });

            // hold onto an instance of the grid
            $('#templates-table').data('gridInstance', templatesGrid);

            // initialize the number of displayed items
            $('#displayed-templates').text('0');
        },

        /**
         * Update the size of the grid based on its container's current size.
         */
        resetTableSize: function () {
            var templateGrid = $('#templates-table').data('gridInstance');
            if (nfCommon.isDefinedAndNotNull(templateGrid)) {
                templateGrid.resizeCanvas();
            }
        },

        /**
         * Load the processor templates table.
         */
        loadTemplatesTable: function () {
            return $.ajax({
                type: 'GET',
                url: config.urls.templates,
                dataType: 'json'
            }).done(function (response) {
                // ensure there are groups specified
                if (nfCommon.isDefinedAndNotNull(response.templates)) {
                    var templatesGrid = $('#templates-table').data('gridInstance');
                    var templatesData = templatesGrid.getData();

                    // set the items
                    templatesData.setItems(response.templates);
                    templatesData.reSort();
                    templatesGrid.invalidate();

                    // update the stats last refreshed timestamp
                    $('#templates-last-refreshed').text(response.generated);

                    // update the total number of processors
                    $('#total-templates').text(response.templates.length);
                } else {
                    $('#total-templates').text('0');
                }
            }).fail(nfErrorHandler.handleAjaxError);
        }
    };
}));