# Copyright 2014 VMware, Inc.  All rights reserved. -- VMware Confidential
#
'''Component script execution progress reporter.
'''
import logging

from .execution_settings import getCoreExecutionSettings
from .componentStatus import ProgressData
from .defaultStatusFunctor import createSimpleComponentProgressUpdater

class ProgressReporter(object):
   def __init__(self, setting = None, updateFun = None, statusFile = None):
      '''Reporter constructor

      @param setting: the execution setting. If unset, global
      execution setting will be used
      @type setting: CoreExecutionSettings

      @param updateFun: customized functor to update internal
      progress for a component. If not specified, a default functor
      updates to a local file (specified via statusFile) a serialized
      ComponentsExecutionStatusInfo instance.
      @type updateFun: functor, the input is progress, it updates the
      internal storage with new progress status.

      @param statusFile: Currently used when updateFun is unset, when
      it is used to specify status file. It is ignored if updateFun is set.
      @type statusFile: string
      '''
      if not setting:
         self._cName = getCoreExecutionSettings().componentName
      else:
         self._cName = setting.componentName
      assert(self._cName)
      
      if not updateFun:
         assert(statusFile)
         self._updateFun = createSimpleComponentProgressUpdater(statusFile,
                                                                self._cName)
      else:
         self._updateFun = updateFun

   def _updateProgress(self, progress):
      '''Updates the progress of the component.

      @param progress: the progress status
      @type progress: ProgressData
      '''
      try:
         self._updateFun(progress)
      except Exception:
         logging.exception("Error in updating progress")

   def updateProgress(self, percentage, message=None):
      '''Updates the progress of the component.

      @param percentage: the progress percentage
      @type percentage: integer

      @param message: the progress status message
      @type message: LocalizableMessage
      '''
      progress = ProgressData(percentage=percentage,
                              progress_message=message)
      self._updateProgress(progress)

   def success(self, message=None):
      '''Notifies that the component execution completed successfully.

      @param message: The message describing the completion.
      @param message: LocalizableMessage
      '''
      progress = ProgressData(ProgressData.State.SUCCESS, 100, message)
      self._updateProgress(progress)

   def failure(self, errInfo):
      '''Notifies that the component execution failed.

      @param errInfo: The error information from exception which caused the failure
      @type errInfo: ErrorInfo
      '''
      if not errInfo.componentKey:
         errInfo.componentKey = self._cName
      progress = ProgressData(status = ProgressData.State.ERROR,
                              progress_message = errInfo)
      self._updateProgress(progress)
