from calculation.errors import CalculationError

from storage.errors import StorageCreationFailedException
from storage.factory import StorageFactory

from task.states.base import TaskStateBase
from task.states.error import TaskErrorState
from task.states.running import TaskRunningState


class TaskSetUpState(TaskStateBase):
    def __init__(self, task):
        super().__init__(task)
        try:
            self.__storage = StorageFactory.create()
        except (StorageCreationFailedException, Exception) as exc:
            # Catch all storage errors - storage is optional
            self._task.logger.error("Cannot connect to object storage")
            self._task.logger.info("Continuing, because it is possible to not use it at all")
            self._task.logger.debug(str(exc))
            self.__storage = None  # Explicitly set to None

    @property
    def name(self):
        return "set up"

    def run(self):
        try:
            self._task.logger.info("Run set up phase of calculation")
            self.__fetch_configured_objects()
            self._task.calculation.set_up()
            self._task.change_state(TaskRunningState(self._task))
        except CalculationError as calculation_error:
            self._task.logger.error("Calculation error occured during set up phase")
            self._task.logger.exception(calculation_error)
            self._task.change_state(TaskErrorState(self._task))

    def __fetch_configured_objects(self):
        for obj in self._task.configuration.objects:
            self.__storage.download_file(obj.local, obj.remote)
