// Copyright 1999-2017. Plesk International GmbH. All Rights Reserved.

Jsw.onReady(function() {
    // Global variable representing current status of migration. Updated periodically with AJAX request.
    var statusData = MIGRATION_STATUS_DATA;

    function createGroupOperationButton(operationName, onApplied) {
        var operation = findOperation(operationName);
        return {
            componentType: 'Jsw.SmallButton',
            id: 'button' + operation.name,
            title: migratorLocale.lmsg(operation.titleGroupOperation),
            description: migratorLocale.lmsg(operation.descriptionGroupOperation),
            handler: function() {
                runGroupOperation(operation, operationOnSuccessHandler(operation));
            }
        }
    }

    function operationOnSuccessHandler(operation)
    {
        var onSuccess = null;
        if (operation.listReload) {
            if (operation.showIPMapping) {
                onSuccess = function () {
                    showIPMapping = true;
                    configureIPColumn();
                    list.reload();
                };
            } else {
                onSuccess = function () {
                    list.reload();
                };
            }
        } else {
            onSuccess = resetSubscriptionSelection;
        }
        return onSuccess;
    }

    // Execute specified function for each subscription in the list.
    // Callback function should accept 2 arguments - subscription name and list row (<tr>) element.
    function foreachListSubscription(callback) {
        $$('.subscription-name').each(function (element) {
            var subscriptionName = element.textContent;
            var row = element.up('tr');
            callback(subscriptionName, row);
        });
    }

    var showIPMapping = false;

    // Get list of subscription names, selected for group operations by checkbox in the first column of the table
    function getSelectedSubscriptions() {
        var selectedSubscriptions = [];

        foreachListSubscription(function(subscriptionName, row) {
            var checkbox = row.select('input[type="checkbox"]').first();
            if (checkbox.checked) {
                selectedSubscriptions.push(subscriptionName);
            }
        });

        return selectedSubscriptions;
    }

    // Reset selection of subscriptions for group operations. Use this function once some group operation was
    // scheduled or started
    function resetSubscriptionSelection() {
        foreachListSubscription(function(subscriptionName, row) {
            var checkbox = row.select('input[type="checkbox"]').first();
            row.removeClassName('selected');
            checkbox.checked = false;
        });
        $$('input[name="listGlobalCheckbox"]').each(function(checkbox) {
            checkbox.checked = false;
        });
    }

    // Run group operation for selected subscriptions.
    function runGroupOperation(operation, onSuccess) {
        if (!list.checkNonEmptySelection()) {
             return;
        }

        var selectedSubscriptions = getSelectedSubscriptions();

        var operationApplicable = true;
        selectedSubscriptions.each(function(subscriptionName) {
            var item = list.getSubscriptionItem(subscriptionName);
            if (!operation.isApplicable(item)) {
                operationApplicable = false;
            }
        });
        if (operationApplicable) {
            list.hideItemsInvalidStatusWarning();
        } else {
            list.showItemsInvalidStatusWarning();
            return;
        }

        if (onSuccess) {
            operation.run(selectedSubscriptions, onSuccess);
        } else {
            operation.run(selectedSubscriptions);
        }
    }

    // Configure action handlers for per-subscription actions at the last column of the table,
    // for example "Migrate", "Re-sync", etc.
    function configureActionHandlers() {
        foreachListSubscription(function(subscriptionName, row) {
            subscriptionOperations.each(function(subscriptionOperator) {
                observeClickOnChildElement(
                    row, 'action-' + subscriptionOperator.name, function(actionElement) {
                        subscriptionOperator.run([subscriptionName]);
                    }
                );
            });

            subscriptionStatusOperations.each(function(subscriptionStatusOperation) {
                observeClickOnChildElement(row, 'action-details-' + subscriptionStatusOperation.name, function() {
                    var issues = getPropertyChain(
                        statusData, ['subscriptionIssues', subscriptionName], []
                    ).filter(
                        function(issue) {
                            return issue.executionCommandOperation == subscriptionStatusOperation.name;
                        }
                    );

                    showIssuesPopupDialog(
                        migratorLocale.lmsg('issuesPopupTitleSubscription', {'subscription': subscriptionName}),
                        issues
                    );
                });
            });
        });
    }

    // Configure IP column: display icon with tooltip or full mapping text, create tooltip
    function configureIPColumn()
    {
        foreachListSubscription(function(subscriptionName, row) {
            var ipMappingBlock = row.select('div[class="ipMappingBlock"]').first();
            var ipMappingTooltip = row.select('div[class="ipMappingTooltip"]').first();
            ipMappingBlock.toggle(showIPMapping);
            ipMappingTooltip.toggle(!showIPMapping);

            if (!showIPMapping) {
                Jsw.Tooltip.init(ipMappingTooltip, {text: ipMappingBlock.innerHTML});
            }
        });
    }

    // Configure owner column: display hint
    function configureOwnerColumn()
    {
        foreachListSubscription(function(subscriptionName, row) {
            var ownerBlock = row.select('div[class="ownerBlock"]').first();
            var ownerTooltipBlock = row.select('div[class="ownerTooltipBlock"]').first();

            Jsw.Tooltip.init(ownerBlock, {text: ownerTooltipBlock.innerHTML});
        });
    }

    // Create subscriptions list table, with group operations and search
    var groupOperations = [];

    groupOperations.push(createGroupOperationButton(subscriptionOperation.MIGRATE));
    groupOperations.push({
        componentType: 'Jsw.bar.Separator'
    });
    if (IS_DNS_SWITCH_SUPPORTED) {
        groupOperations.push(createGroupOperationButton(subscriptionOperation.SWITCH_DNS));
    }
    groupOperations.push({
        componentType: 'Jsw.list.AdditionalActions',
        title: migratorLocale.lmsg('subscriptionsListButtonReassignTitle'),
        operations: [
            createGroupOperationButton(subscriptionOperation.REASSIGN_OWNER),
            createGroupOperationButton(subscriptionOperation.REASSIGN_PLAN),
            createGroupOperationButton(subscriptionOperation.RESET_REASSIGN)
        ]
    });

    var ipOperations = [
        {
            componentType: 'Jsw.SmallButton',
            id: 'buttonShowIpMapping',
            title: migratorLocale.lmsg('subscriptionsListButtonShowIpMappingTitle'),
            description: migratorLocale.lmsg('subscriptionsListButtonShowIpMappingHint'),
            handler: function() {
                showIPMapping = true;
                configureIPColumn();
            }
        }
    ];
    if (IS_PLESK_MULTISERVER) {
        ipOperations.push(createGroupOperationButton(subscriptionOperation.SELECT_NODE));
    } else {
        ipOperations.push(createGroupOperationButton(subscriptionOperation.CHANGE_IP_MAPPING));
    }

    groupOperations.push({
        componentType: 'Jsw.list.AdditionalActions',
        title: migratorLocale.lmsg('subscriptionsListButtonIpAddressesTitle'),
        operations: ipOperations
    });
    groupOperations.push(createGroupOperationButton(subscriptionOperation.RESYNC));
    groupOperations.push(createGroupOperationButton(subscriptionOperation.POST_MIGRATION_CHECKS));
    groupOperations.push({
        componentType: 'Jsw.bar.Separator'
    });
    if (IS_DNS_SWITCH_SUPPORTED) {
        groupOperations.push(createGroupOperationButton(subscriptionOperation.REVERT_DNS));
    }
    groupOperations.push(createGroupOperationButton(subscriptionOperation.REMOVE_FROM_QUEUE));
    groupOperations.push(createGroupOperationButton(subscriptionOperation.REMOVE_MIGRATED));

    var menuActions = [
        subscriptionOperation.SWITCH_DNS,
        subscriptionOperation.REVERT_DNS,
        subscriptionOperation.REASSIGN_OWNER,
        subscriptionOperation.REASSIGN_PLAN,
        subscriptionOperation.RESET_REASSIGN,
        subscriptionOperation.CHANGE_IP_MAPPING,
        subscriptionOperation.POST_MIGRATION_CHECKS
        // TODO: implement support
        /* subscriptionOperation.SHOW_LOG */
    ];

    var listItemActions = {};
    menuActions.each(function(menuAction) {
        var operation = findOperation(menuAction);
        listItemActions[menuAction] = function(item) {
            var onSuccess = operationOnSuccessHandler(operation);
            operation.run([item.subscription], onSuccess);
        }
    });

    var SubscriptionsList = Class.create(Jsw.List, {
        _splitListData: function($super, listData, place) {
            if (!listData || !listData.data) {
                return false;
            }

            var self = this;
            listData.data.each(function(item) {
                item.actions = self.getItemActions(item);
            });

            $super(listData, place);
        },
        getSubscriptionItem: function(subscriptionName) {
            for (var i = 0; i < this._data.length; i++) {
                var item = this._data[i];
                if (item.subscription == subscriptionName) {
                    return item;
                }
            }
        },
        getItemActions: function(item) {
            var actions = [];

            menuActions.each(function(menuAction) {
                var operation = findOperation(menuAction);
                if (operation.isApplicable(item)) {
                    actions.push({
                        'name': menuAction,
                        'title': migratorLocale.lmsg(operation.titleMenu),
                        'href': 'javascript:;'
                    });
                }
            });

            return actions;
        },
        updateSubscriptionStatus: function(subscriptionName, operationStatus) {
            var changed = false;
            for (var i = 0; i < this._data.length; i++) {
                var item = this._data[i];
                var subscriptionOperationStatus = getPropertyChain(
                    statusData, ['subscriptions', item.subscription, 'operationStatus'], null
                );

                if (!(objectsEqual(item.operationStatus, subscriptionOperationStatus))) {
                    item.operationStatus = subscriptionOperationStatus;
                    item.actions = this.getItemActions(item);
                    changed = true;
                }
            }

            if (changed) {
                this._contextMenu.onRedraw();
            }
        },
        _itemActions: listItemActions,
        showItemsInvalidStatusWarning: function() {
            this.hideItemsInvalidStatusWarning();
            var element = this._componentElement.down('items-invalid-status-warning');
            if (element) {
                element.show();
            } else {
                this._componentElement.down('.actions-box').insert({
                    top: (
                        '<div class="actions-msg-container" id="items-invalid-status-warning">' +
                            '<span class="list-actions-msg">' +
                                '<span>' +
                                    migratorLocale.lmsg('subscriptionsListOperationsCanNotBeApplied') +
                                '</span>' +
                            '</span>' +
                        '</div>'
                    )
                });
            }
        },
        hideItemsInvalidStatusWarning: function() {
            var element = this._componentElement.down('.actions-msg-container');
            if (element) {
                element.hide();
            }
        }
    });

    var list = new SubscriptionsList({
        id: 'migration-subscriptions-list',
        data: SUBSCRIPTIONS_LIST_DATA,
        dataUrl: URL_SUBSCRIPTIONS_LIST,
        searchFilters: SUBSCRIPTIONS_LIST_FILTER_CONFIG,
        searchOveral: 'subscription',
        operations: groupOperations,
        itemActions: listItemActions,
        columns: [
            Jsw.list.COLUMN_SELECTION,
            {
                header: migratorLocale.lmsg('subscriptionsListTableSubscription'),
                dataIndex: 'subscription',
                sortable: true,
                renderer: function(item, isDisabled) {
                    var html = '';

                    // Hidden content to identify subscription name for each table row
                    html += '<div class="subscription-name" style="display: none;">';
                    html += formatStr(item.subscription);
                    html += '</div>';
                    html += '<div class="subscription-name-normalized" style="display: none;">';
                    html += formatStr(item.subscriptionNameNormalized);
                    html += '</div>';

                    // Displayed content: 2 blocks:
                    // 1) Plain subscription name, if subscription does not exist in Plesk
                    // 2) Subscription name with link to overview page in Plesk, if subscription exists in Plesk
                    html += '<span class="subscription-name-plain">';
                    html += formatStr(item.subscription);
                    html += '</span>';

                    html += '<span class="subscription-name-link" style="display: none;">';
                    html += '<a href="">' + formatStr(item.subscription) + '</a>';
                    html += '</span>';

                    return html;
                }
            },
            {
                header: migratorLocale.lmsg('subscriptionsListTableOwner'),
                dataIndex: 'owner',
                renderer: function(item, isDisabled) {
                    var html = '';

                    // Format tooltip block: invisible, but used by configureOwnerColumn funtion, which creates
                    // tooltip control
                    html += '<div class="ownerTooltipBlock" style="display: none">';

                    function formatTitleTooltip(login, title) {
                        if (title) {
                            return title.escapeHTML() + ' (' + login.escapeHTML() + ')';
                        } else {
                            return login.escapeHTML();
                        }
                    }

                    if (item.ownerResellerLogin) {
                        if (item.ownerCustomerLogin) {
                            html += formatMessage(
                                migratorLocale.lmsg('hintOwnerByCustomerOwnedByReseller'),
                                formatTitleTooltip(item.ownerCustomerLogin, item.ownerCustomerTitle),
                                formatTitleTooltip(item.ownerResellerLogin, item.ownerResellerTitle)
                            );
                        } else {
                            html += formatMessage(
                                migratorLocale.lmsg('hintOwnedByReseller'),
                                formatTitleTooltip(item.ownerResellerLogin, item.ownerResellerTitle)
                            );
                        }
                    } else if (item.ownerCustomerLogin) {
                        html += formatMessage(
                            migratorLocale.lmsg('hintOwnerByCustomer'),
                            formatTitleTooltip(item.ownerCustomerLogin, item.ownerCustomerTitle)
                        );
                    } else {
                        html += migratorLocale.lmsg('hintOwnedByAdministrator');
                    }
                    html += '</div>';

                    // Format regularly displayed block
                    html += '<div class="ownerBlock">';

                    function formatTitleTable(login, title) {
                        if (title) {
                            return title.escapeHTML();
                        } else {
                            return login.escapeHTML();
                        }
                    }

                    if (item.ownerResellerLogin) {
                        html +=
                            '<div><img src="' + migratorImage('subscriptions-list-reseller.png') + '" alt="Reseller">' +
                                formatTitleTable(item.ownerResellerLogin, item.ownerResellerTitle) +
                            '</div>';
                    }
                    if (item.ownerCustomerLogin) {
                        html +=
                            '<div>' +
                                formatTitleTable(item.ownerCustomerLogin, item.ownerCustomerTitle) +
                            '</div>';
                    }
                    if (!item.ownerCustomerLogin && !item.ownerResellerLogin) {
                        html +=
                            '<div>' +
                                migratorLocale.lmsg('administratorTitle') +
                            '</div>';
                    }
                    if (item.reassignOwner) {
                        html +=
                            '<div class="reassign-text">(' +
                                formatMessage(migratorLocale.lmsg('reassignedTo'), item.reassignOwner.escapeHTML()) +
                            ')</div>';
                    }
                    html += '</div>';

                    return html
                },
                sortable: true
            },
            {
                header: migratorLocale.lmsg('subscriptionsListTablePlan'),
                dataIndex: 'plan',
                renderer: function(item, isDisabled) {
                    var html = '<div>' + item.plan.escapeHTML() + '</div>';
                    if (item.reassignPlan) {
                        html += (
                            '<div class="reassign-text">(' +
                            formatMessage(migratorLocale.lmsg('reassignedTo'), item.reassignPlan.escapeHTML()) +
                            ')</div>'
                        );
                    }
                    return html
                },
                sortable: true
            },
            {
                header: migratorLocale.lmsg('subscriptionsListTableIP'),
                dataIndex: 'ip',
                sortable: true,
                renderer: function(item, isDisabled) {
                    var ipBlock = '';
                    if (HAS_IPV6_ADDRESSES || item.nodeIP) {
                        ipBlock += '<div>' + formatMessage(migratorLocale.lmsg('ipv4Address'), item.ipv4) + '</div>';
                        ipBlock += '<div>' + formatMessage(migratorLocale.lmsg('ipv6Address'), item.ipv6) + '</div>';
                        if (item.nodeIP) {
                            ipBlock += '<div>' + formatMessage(migratorLocale.lmsg('nodeIP'), item.nodeIP) + '</div>';
                        }
                    } else {
                        ipBlock += item.ipv4;
                    }
                    var html = '';
                    html += '<div style="display: none;" class="ipMappingBlock">' + ipBlock + '</div>';
                    html += '<div style="display: none;" class="ipMappingTooltip"><img src="' + migratorImage('server-info-toolbar-subscriptions.png') + '"></div>';
                    return html;
                }
            },
            {
                header: migratorLocale.lmsg('subscriptionsListTableStatus'),
                dataIndex: 'status',
                sortable: true,
                renderer: function (item, isDisabled) {
                    var html = '';
                    subscriptionStatusOperations.each(function(subscriptionStatusOperation) {
                        subscriptionStatuses.each(function(subscriptionStatus) {
                            html += '<div class="subscription-status-' + subscriptionStatus.name + '-' + subscriptionStatusOperation.name + '" style="display: none;">';
                            if (subscriptionStatus.imageSubscriptionsList) {
                                html += '<img src="' + subscriptionStatus.imageSubscriptionsList + '" style="width: 16px; height: 16px;">&nbsp;';
                            } else {
                                html += '<img src="' + migratorImage('server-info-toolbar-subscriptions.png') + '" style="width: 16px; height: 16px;">&nbsp;';
                            }
                            html += migratorLocale.lmsg(subscriptionStatusOperation.titleSubscriptionsList) + ' - <span class="status-text-' + subscriptionStatus.name + '">';
                            html += migratorLocale.lmsg(subscriptionStatus.titleSubscriptionsList);
                            html += '</span>';
                            if (subscriptionStatus.showDetailsAction) {
                                html += '&nbsp;';
                                html += '<a class="action-details-' + subscriptionStatusOperation.name + '" href="javascript:;">' + migratorLocale.lmsg('actionDetails') + '</a>';
                            }

                            html += '</div>';
                        });
                    });

                    return html;
                }
            },
            {
                header: migratorLocale.lmsg('subscriptionsListTableActions'),
                dataIndex: 'actions',
                sortable: false,
                renderer: function(item, isDisabled) {
                    var html = '';
                    subscriptionOperations.each(function(subscriptionOperation) {
                        if (!migratorLocale.lmsg(subscriptionOperation.titleMain)) {
                            return;
                        }

                        html += '<div class="subscription-main-action-' + subscriptionOperation.name + '" style="display: none;">';
                            html += '<a href="javascript:;" class="action-' + subscriptionOperation.name + '">';
                                html += migratorLocale.lmsg(subscriptionOperation.titleMain);
                            html += '</a>';
                        html += '</div>';
                    });
                    return html;
                }
            },
            Jsw.list.COLUMN_ACTIONS
        ],
        onRedraw: function() {
            configureActionHandlers();
            configureIPColumn();
            configureOwnerColumn();
        }
    });

    new Jsw.Panel({
        cls: 'list-box',
        renderTo: 'main',
        items: [list]
    });

    function updateMigrationStatus()
    {
        foreachListSubscription(function(subscriptionName, row) {
            var subscriptionInfo = getPropertyChain(statusData, ['subscriptions', subscriptionName], {});
            var operationStatus =  getPropertyChain(subscriptionInfo, ['operationStatus'], {});

            // Toggle operations menu
            subscriptionStatusOperations.each(function(subscriptionStatusOperation) {
                var currentSubscriptionStatus = getPropertyChain(
                    operationStatus, [subscriptionStatusOperation.name], statuses.NOT_STARTED
                );

                subscriptionStatuses.each(function(currentStatus) {
                    toggleChildElement(
                        row, 'subscription-status-' +  currentStatus.name + '-' + subscriptionStatusOperation.name,
                        (
                            currentSubscriptionStatus == currentStatus.name &&
                            (
                                currentStatus.name != statuses.NOT_STARTED ||
                                subscriptionStatusOperation.displayAlways
                            )
                        )
                    )
                });
            });

            // Toggle main operation
            subscriptionOperations.each(function(subscriptionOperation) {
                toggleChildElement(
                    row, 'subscription-main-action-' + subscriptionOperation.name,
                    subscriptionOperation.isMain(subscriptionInfo)
                )
            });

            // Toggle details button
            subscriptionStatusOperations.each(function(subscriptionStatusOperation) {
                var issues = getPropertyChain(
                    statusData, ['subscriptionIssues', subscriptionName], []
                ).filter(
                    function (issue) {
                        return issue.executionCommandOperation == subscriptionStatusOperation.name;
                    }
                );
                toggleChildElement(
                    row,
                    'action-details-' + subscriptionStatusOperation.name, issues.length > 0
                );
            });


            // Update subscription name column - show link to subscription overview page if subscription
            // exists in Plesk
            var subscriptionNameNormalized = getChildElementText(row, 'subscription-name-normalized');
            var pleskSubscriptionUrl = getPropertyChain(
                statusData, ['pleskSubscriptionUrls', subscriptionNameNormalized], null
            );
            var linkExists = pleskSubscriptionUrl !== null;
            toggleChildElement(row, 'subscription-name-plain', !linkExists);
            toggleChildElement(row, 'subscription-name-link', linkExists);
            if (pleskSubscriptionUrl) {
                var link = row.select('.subscription-name-link').first().select('a').first();
                link.writeAttribute('href', pleskSubscriptionUrl);
            }
        });

        list.updateSubscriptionStatus();
    }

    // Update status of each subscription periodically with AJAX
    function periodicUpdateMigrationStatus() {
        new Ajax.Request(URL_GET_MIGRATION_STATUS, {
            onSuccess: function (response) {
                // assign new status data into global variable
                statusData = response.responseText.evalJSON();
                updateMigrationStatus();
            },
            onComplete: function() {
                setTimeout(function() {periodicUpdateMigrationStatus()}, 2000);
            }
        })
    }

    updateMigrationStatus();
    periodicUpdateMigrationStatus();
});