// 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;

    // Run specified function for each customer in results column (from raw migration list)
    // callback - function that receives 2 arguments: customer login as string and status item HTML element
    function foreachResultCustomer(callback) {
        $$('.customerStatus').each(function(element) {
            var customerLogin = element.select(".customerLogin")[0].textContent.strip();
            callback(customerLogin, element);
        });
    }

    // Run specified function for each reseller in results column (from raw migration list)
    // callback - function that receives 2 arguments: reseller login as string and status item HTML element
    function foreachResultReseller(callback) {
        $$('.resellerStatus').each(function(element) {
            var resellerLogin = element.select(".resellerLogin")[0].textContent.strip();
            callback(resellerLogin, element);
        });
    }

    // Run specified function for each subscription in results column (from raw migration list)
    // callback - function that receives 2 arguments: subscription name as string and status item HTML element
    function foreachResultSubscription(callback) {
        $$('.subscription-finished').each(function (element) {
            var subscriptionName = element.select(".subscription-name")[0].textContent.strip();
            callback(subscriptionName, element)
        });
    }

    // Run specified function for each subscription in queue column (from raw migration list)
    // callback - function that receives 2 arguments: subscription name as string and queue item HTML element
    function foreachQueueSubscription(callback) {
        $$('.subscription-in-progress').each(function (element) {
            var subscriptionName = element.select(".subscription-name")[0].textContent.strip();
            callback(subscriptionName, element);
        });
    }

    // Run specified function for overall result
    // callback - function that receives 1 argument: overall item HTML element
    function forResultOverall(callback) {
        var overallElement = $$('.overallStatus')[0];
        callback(overallElement);
    }

    // Root update function: called once we get new data about migration status with AJAX request
    function updateMigrationStatus()
    {
        updateQueue();
        updatePreChecks();
        updateResults();
    }

    // Update left column: migration queue
    function updateQueue()
    {
        updateQueueOverallAction();
        updateQueueCount();
        updateQueueSubscriptions();
    }

    // Update right column: migration results
    function updateResults()
    {
        updateResultsSubscription();
        updateResultsReseller();
        updateResultsCustomer();
        updateResultsOverall();
        updateSubscriptionCounts();
    }

    // Update overall action - action executed on all subscriptions
    function updateQueueOverallAction()
    {
        if (statusData.overall.action) {
            $('overall-status-text').textContent = getPropertyChain(statusData, ['overall', 'action'], '');
            $('overall-status').show();
        } else {
            $('overall-status').hide();
        }
    }

    // Update number of subscriptions in queue
    function updateQueueCount()
    {
        $('queue-count').textContent  = countItems(
            getPropertyChain(statusData, ['subscriptions'], []), function(_, subscription) {
                return inArray(subscription.status, [statuses.IN_PROGRESS, statuses.ON_HOLD])
            }
        );
    }

    function updatePreChecks()
    {
        var preCheckTasksCount = 0;
        $$('.migration-status-pre-check-task').each(function(element) {
            var taskId = getChildElementText(element, 'task-id');
            var taskStatus = getPropertyChain(statusData, ['preCheckTasks', taskId, 'status'], null);
            if (taskStatus == 'not-started' || taskStatus == 'pre-checks-completed') {
                var link = element.select('a').first();
                link.stopObserving('click');
                link.observe('click', function() {
                    showPreChecksPopup(taskId, false);
                });
                element.show();
                preCheckTasksCount++;
            } else {
                element.hide();
            }
        });
        $('migration-status-block-pre-checks').toggle(preCheckTasksCount > 0);
    }

    // Update status of each subscription in queue
    function updateQueueSubscriptions()
    {
        foreachQueueSubscription(function(subscriptionName, element) {
            var subscriptionStatus = getPropertyChain(
                statusData, ['subscriptions', subscriptionName, 'status'], statuses.NOT_STARTED
            );
            var action = getPropertyChain(
                statusData, ['subscriptions', subscriptionName, 'action'], ''
            );
            var details = getPropertyChain(
                statusData, ['subscriptions', subscriptionName, 'details'], ''
            );
            toggleChildElement(
                element, 'image-status-in-progress', subscriptionStatus == statuses.IN_PROGRESS
            );
            toggleChildElement(
                element, 'image-status-on-hold', subscriptionStatus == statuses.ON_HOLD
            );
            element.toggle(inArray(subscriptionStatus, [statuses.IN_PROGRESS, statuses.ON_HOLD]));

            var statusTextElement = element.select(".status-text")[0];
            var detailsTextElement = element.select(".details-text")[0];
            var detailsTextContainer = element.select(".details-text-container")[0];

            var showAction = (
                action &&
                // Show action text only if subscription is "In progress". There could be situation when
                // progress file (which contains action) and subscription status files (which contains status)
                // are not in sync. For example, we need such check to avoid display actions for
                // subscriptions marked as "On hold".
                subscriptionStatus == statuses.IN_PROGRESS
            );

            if (showAction) {
                statusTextElement.textContent = action;
                if (detailsTextElement && detailsTextContainer) {
                    detailsTextElement.textContent = details;
                    if (details) {
                        detailsTextContainer.show();
                    } else {
                        detailsTextContainer.hide();
                    }
                }
            } else {
                statusTextElement.textContent = '';
                if (detailsTextElement && detailsTextContainer) {
                    detailsTextElement.textContent = '';
                    detailsTextContainer.hide();
                }
            }

            toggleChildElement(element, 'status-separator', showAction);
            toggleChildElement(element, 'status-text', showAction);

            updateSubscriptionNameColumn(element);
        });
    }

    // Update migration results for subscriptions
    function updateResultsSubscription()
    {
        var hasSubscriptionsDisplayed = false;
        foreachResultSubscription(function(subscriptionName, element) {
            var issues = getPropertyChain(
                statusData, ['subscriptionIssues', subscriptionName], []
            );
            var status = getPropertyChain(
                statusData, ['subscriptions', subscriptionName, 'status'], statuses.NOT_STARTED
            );

            var isStatusFinished = inArray(
                status, [statuses.FINISHED_OK, statuses.FINISHED_WARNINGS, statuses.FINISHED_ERRORS]
            );
            var isStatusQueued = inArray(
                status, [statuses.IN_PROGRESS, statuses.ON_HOLD]
            );
            // Show subscription in 2 cases:
            // 1) There are issues for that subscription (even if migration is still running).
            // 2) Migration of the subscription finished.
            if (issues.length > 0 || isStatusFinished) {
                // Show status of the last operation for subscription, if available - otherwise detect by issues
                if (isStatusFinished) {
                    updateStatusImageByStatus(element, status);
                } else {
                    updateStatusImageByIssues(element, issues)
                }
                toggleChildElement(
                    element, 'action-resync',
                    (
                        !isStatusQueued &&
                        status != statuses.NOT_STARTED &&
                        status != statuses.CANCELLED
                    )
                );
                element.show();
                hasSubscriptionsDisplayed = true;
            } else {
                element.hide();
            }

            updateSubscriptionNameColumn(element);
        });
        $('migration-status-block-results-subscription').toggle(hasSubscriptionsDisplayed);
    }

    // Update migration results for resellers
    function updateResultsReseller()
    {
        var hasResellerWithIssues = false;
        foreachResultReseller(function(resellerLogin, element) {
            var issues = getPropertyChain(statusData, ['resellerIssues', resellerLogin], []);
            element.toggle(issues.length > 0);
            hasResellerWithIssues = hasResellerWithIssues || issues.length > 0;
        });
        $('migration-status-block-results-reseller').toggle(hasResellerWithIssues);
    }

    // Update migration results for customer
    function updateResultsCustomer()
    {
        var hasCustomerWithIssues = false;
        foreachResultCustomer(function(customerLogin, element) {
            var issues = getPropertyChain(statusData, ['customerIssues', customerLogin], []);
            element.toggle(issues.length > 0);
            hasCustomerWithIssues = hasCustomerWithIssues || issues.length > 0;
        });
        $('migration-status-block-results-customer').toggle(hasCustomerWithIssues);
    }

    // Update overall migration results
    function updateResultsOverall()
    {
        forResultOverall(function(element) {
            var issues = getPropertyChain(statusData, ['overallIssues'], []);
            $('migration-status-block-results-overall').toggle(issues.length > 0);
        });
    }

    // Update counts of successful/failed subscriptions
    function updateSubscriptionCounts()
    {
        // update right column: list of finished subscriptions
        $('success-count').textContent = countItems(
            statusData.subscriptions, function(_, subscription) {
                return subscription.status == statuses.FINISHED_OK;
            }
        );
        $('failed-count').textContent= countItems(
            statusData.subscriptions, function(_, subscription) {
                return subscription.status == statuses.FINISHED_ERRORS;
            }
        );
        $('warning-count').textContent = countItems(
            statusData.subscriptions, function(_, subscription) {
                return subscription.status == statuses.FINISHED_WARNINGS;
            }
        );
    }

    // Update migration status periodically with AJAX
    function periodicUpdateMigrationStatus() {
        new Ajax.Request(URL_GET_MIGRATION_STATUS, {
            onSuccess: function (response) {
                statusData = response.responseText.evalJSON();
                updateMigrationStatus();
            },
            onComplete: function() {
                setTimeout(function() {periodicUpdateMigrationStatus()}, 2000);
            }
        });
    }

    // Utility function to show proper icon according to migration status
    function updateStatusImageByStatus(element, status)
    {
        toggleChildElement(element, 'image-status-success', status == statuses.FINISHED_OK);
        toggleChildElement(element, 'image-status-warning', status == statuses.FINISHED_WARNINGS);
        toggleChildElement(element, 'image-status-failure', status == statuses.FINISHED_ERRORS);
    }

    // Utility function to show proper icon according to issues list
    function updateStatusImageByIssues(element, issues) {
        var hasErrors = containsElement(issues, function(issue) { return issue.severity == issueSeverity.ERROR; });
        var hasWarnings = containsElement(issues, function(issue) { return issue.severity == issueSeverity.WARNING; });
        toggleChildElement(element, 'image-status-success', !hasErrors && !hasWarnings);
        toggleChildElement(element, 'image-status-warning', !hasErrors && hasWarnings);
        toggleChildElement(element, 'image-status-failure', hasErrors);
    }

    function assignControlHandlers() {
        foreachResultSubscription(function(subscriptionName, element) {
            observeClickOnChildElement(element, 'action-resync', function() {
                showResyncPopup([subscriptionName]);
            });
        });

        foreachResultSubscription(function(subscriptionName, element) {
            observeClickOnChildElement(element, 'action-details', function() {
                var issues = getPropertyChain(
                    statusData, ['subscriptionIssues', subscriptionName], []
                );
                showIssuesPopupDialog(
                    migratorLocale.lmsg('issuesPopupTitleSubscription', {'subscription': subscriptionName}),
                    issues
                );
            });
        });

        foreachResultReseller(function(resellerLogin, element) {
            observeClickOnChildElement(element, 'action-details', function() {
                var issues = getPropertyChain(statusData, ['resellerIssues', resellerLogin], []);
                showIssuesPopupDialog(
                    migratorLocale.lmsg('issuesPopupTitleReseller', {'reseller': resellerLogin}),
                    issues
                );
            });
        });

        foreachResultCustomer(function(customerLogin, element) {
            observeClickOnChildElement(element, 'action-details', function() {
                var issues = getPropertyChain(statusData, ['customerIssues', customerLogin], []);
                showIssuesPopupDialog(
                    migratorLocale.lmsg('issuesPopupTitleCustomer', {'customer': customerLogin}),
                    issues
                );
            });
        });

        forResultOverall(function(element) {
            observeClickOnChildElement(element, 'action-details', function() {
                var issues = getPropertyChain(statusData, ['overallIssues'], []);
                showIssuesPopupDialog(
                    migratorLocale.lmsg('issuesPopupTitleOverall'),
                    issues
                );
            });
        });
    }

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

    // Perform initial update from data passed in HTML
    updateMigrationStatus();
    // Schedule run periodic updates with AJAX
    periodicUpdateMigrationStatus();
    // Assign handlers to various action buttons
    assignControlHandlers();
});
