"""Utility functions to print (and save to files) hosting check reports"""

import sys

from parallels.core.logging import get_logger
from parallels.core import messages
from parallels.core.reports.printer import print_report

logger = get_logger(__name__)


def print_backup_hosting_report(report, report_filename=None, exit_with_exit_code=True):
    checks_map = {
        'Apache web sites': 'Apache web site',
        'IIS web sites': 'IIS web site',
        'DNS zones': 'DNS zone',
        'Mail domains': 'Mail domain',
        'FTP service': 'FTP service',
        'SSH service': 'SSH service',
        'RDP service': 'RDP service',
        'Database service': 'Database service',
    }
    checks_order = [
        'Apache web sites', 'IIS web sites', 'DNS zones',
        'Mail domains', 'FTP service', 'SSH service', 'RDP service',
        'Database service'
    ]

    _print_hosting_report(
        report,
        'Subscription',
        checks_map,
        checks_order,
        messages.ALL_TRANSFERRED_DOMAINS_ARE_WORKING_CORRECTLY,
        exit_with_exit_code=exit_with_exit_code,
        report_filename=report_filename
    )


def print_service_hosting_report(report, report_filename=None, exit_with_exit_code=True):
    checks_map = {
        'Service': 'Service',
    }
    checks_order = ['Service']

    _print_hosting_report(
        report,
        'Service',
        checks_map,
        checks_order,
        messages.ALL_SERVICES_ARE_WORKING_CORRECTLY,
        exit_with_exit_code=exit_with_exit_code,
        report_filename=report_filename
    )


def _print_hosting_report(
    report, check_type, checks_map, checks_order, successful_message,
    report_filename=None, exit_with_exit_code=True
):
    """Print report and summary of hosting checks

    Print report and summary of hosting checks with logging module, put some info
    into files

    Arguments:
    - report - hosting report, instance of checking.Report
    - check_type - what we check: service or subscription
    - checks_map - map for checks name
    - checks_order - list of checks in order
    - save_report_function - function which accepts contents of a report 
    (as a string) and returns filename it saved the report to
    - exit_with_exit_code - if this flag is true, then if some of the checks failed - exit with '1' exit code
    """
    def subscriptions_count(report, check_type):
        count = 0
        for child in report.children:
            if child.type == check_type:
                count += 1
            count += subscriptions_count(child, check_type)
        return count

    def check_counts(report, check_type):
        total = 0
        failed = 0
        warnings = 0

        for child in report.children:
            (
                children_total, 
                children_warnings, 
                children_failed
            ) = check_counts(child, check_type)
            total += children_total
            warnings += children_warnings
            failed += children_failed
            if child.type == check_type:
                total += 1
                if child.has_errors():
                    failed += 1
                elif child.has_warnings():
                    warnings += 1

        return total, warnings, failed

    def failed_subscriptions_count(report, check_type):
        count = 0
        for child in report.children:
            if child.type == check_type and child.has_errors():
                count += 1
            count += failed_subscriptions_count(child, check_type)
        return count

    subscriptions_count = subscriptions_count(report, check_type)
    failed_subscriptions_count = failed_subscriptions_count(report, check_type)

    print_report(report, report_filename, show_no_issue_branches=True)

    logger.info(messages.SUMMARY)

    stats = list()
    for check_name in checks_order:
        total, warnings, failed = check_counts(report, checks_map[check_name])
        if total != 0:
            stats.append((
                check_name, 
                total, 
                total - failed - warnings, 
                warnings, 
                failed
            ))

    if len(stats) > 0:
        logger.info(
            messages.SUMMARY_OPERATION_FINISHED_SUCCESSFULLY,
            subscriptions_count - failed_subscriptions_count,
            subscriptions_count,
            'subscriptions' if check_type == 'Subscription' else 'services'
        )

        def print_stats_line(name, total, success, warnings, failed):
            logger.info(u"%-20s %-5s %-10s %-8s %-6s" % (
                name, total, success, warnings, failed
            ))

        print_stats_line(
            messages.SUMMARY_TITLE_CHECKED_OBJECT, messages.SUMMARY_TITLE_TOTAL, messages.SUMMARY_TITLE_SUCCESSFUL,
            messages.SUMMARY_TITLE_WARNINGS, messages.SUMMARY_TITLE_FAILED
        )
        for name, total, success, warnings, failed in stats:
            print_stats_line(name, total, success, warnings, failed)

        if exit_with_exit_code and report.has_issues():
            sys.exit(1)
        else:
            logger.info(successful_message)
    else:
        logger.info(messages.NO_OBJECTS_CHECKED)
