# Copyright 2015-2020 VMware, Inc.  All rights reserved. -- VMware Confidential
#
'''Utilities for setup the reporting sdk
'''
import logging
import os

from status_reporting_sdk.componentStatus import ErrorInfo

import reporting
import l10n
from reporting.reporting_factory import ReportingFactory
from l10n import msgMetadata as _T, localizedString as _
from vmware_b2b.patching.utils.status_aggregator import getStatusAggregator
from vmware_b2b.patching.utils import resource_utils
logger = logging.getLogger(__name__)

FRAMEWORK_COMPONENT = "B2B-patching"

INTERNAL_ERROR_TEXT_WITH_ARGS = _T('patch.internal.error.text',
                                   'Internal error occurs during '
                                   'execution of update process %s.')

INTERNAL_ERROR_TEXT = _(INTERNAL_ERROR_TEXT_WITH_ARGS, [' '])

INTERNAL_ERROR_RESOLUTION = _(_T('patch.internal.error.resolution',
                                 'Send upgrade log files to '
                                 'VMware technical support '
                                 'team for further assistance.'))

def reportProgressError(userError=None, identifier=None, errorText=''):
    ''' Publish that failure occur to the progress reporting, expects that progress
      reporting is set up front

    @param userError: A userError that occur or None if it is not user error
    @type  userError: patch_errors.UserError
    '''
    # TODO Move that in progress method
    progressReporter = None
    if identifier:
        progressReporter = ReportingFactory(reporting.getReportingFactory().reportQueue,
                                            identifier).progressReporter
    else:
        progressReporter = reporting.getProgressReporter()

    if userError:
        progressReporter.failure(ErrorInfo(detail=[userError.cause],
                                           resolution=userError.resolution,
                                           problemId=userError.problemId))
    else:
        progressReporter.failure(ErrorInfo(detail=[_(INTERNAL_ERROR_TEXT_WITH_ARGS,
                                                     [errorText])],
                                           resolution=INTERNAL_ERROR_RESOLUTION))

def createReportingIdentifier(scriptFile, hook):
    ''' Creates and identifer for reporting for the given file and hook.
    @param scriptFile: Script path on the os
    @type scriptFile: str

    @param hook: The patching hook which has to be executed. Allowed values are
      defined at extensions.Hook structure.
    @type hook: str

    @return: a identifier for the provided combination
    @rtype: str
    '''
    return "%s:%s" % (os.path.basename(scriptFile), hook)

def createComponentReportingIdentifier(c, hook):
    ''' Creates and identifer for reporting for the given component and hook.
    @param c: A component which has to be executed
    @type c: vmware.patching.data.model.Component

    @param hook: The patching hook which has to be executed. Allowed values are
      defined at extensions.Hook structure.
    @type hook: str

    @return: a identifier for the provided combination
    @rtype: str
    '''
    return createReportingIdentifier(c.patchScript, hook)

def configureLocalization(locale):
    ''' Configure the localization facilities to use given locale

    @param locale: Given supported locale, for example en, de
    @type locale: str
    '''
    if not locale:
        logger.warning('Skip setting localization due to no locale provided!')
        return
    catalogRoot = os.path.join(resource_utils.getRootDirectory(), 'resource', 'locale')
    l10n.configure(catalogRoot, locale)

def configureReportingFactory(identifier, reportQueue, reportErrors=True):
    ''' Configure the global ReportingFactory

    @param identifier: Identifier to identify messages from the MessageDispatcher
    @type identifier: str

    @param reportQueue: A queue to report any messages, questions and progress reports.
    @type reportQueue: multiprocessor.Queue

    @param reportErrors: Report errors from the execution. If it is False,
        just will log them
    @type reportErrors: bool
    '''
    logger.info('Setting global ReportingFactory with identifier - %s', identifier)
    reporting._reportingFactory = ReportingFactory(reportQueue, identifier, reportErrors)

def setupReporting(outputFile, trackedReporters, completedReporters=None):
    '''Setup the reporting module to report the progress and the status of
      current operation into the output file

    @param outputFile: Status output file
    @type outputFile: str

    @param trackedReporters: how many components will report to this module
    @type trackedReporters: int

    @param completedReporters: how many components have already being done.
        This is used when the reporting should resume from previous reporting
        that was done in the previous execution.
    @type completedReporters: int

    @return: StatusAggregator to control reporting
    '''
    statusAggregator = getStatusAggregator(trackedReporters, outputFile, completedReporters=completedReporters)
    statusAggregator.start()
    return statusAggregator
