# -*- coding: utf-8 -*-

"""
Транспорт - это объект, доставляющий данные из удаленного источника. Здесь
описан базовый класс для всех транспортов (L{Transport}) и фабрика
(L{TransportFactory}), позволяющая создавать транспорт по его имени.
"""
import time
from stocks3.core.config import Configurable
from stocks3.core.exception import S3Exception, throw_only

__author__ = "Zasimov Alexey"
__email__ = "zasimov-a@yandex-team.ru"


class S3TransportError(S3Exception):
    STAGE = "transport"


class Transport(Configurable):
    """
    Транспорт доставляет данные из удаленного источника в указанное место
    (place).
    """

    def __init__(self, tree, node, source):
        """
        Создает новый транспорт.
        """
        self.source = source
        if tree is not None and node is not None:
            Configurable.__init__(self, tree, node)

    def transfer(self, place):
        """
        Передает данные из источника в место place. Есть вероятность, что
        транспорт будет передавать данные в нескольких файлах. То есть place -
        это либо файл, либо директория.

        Если транспорт работает только с конкретным местом, он должен
        генерировать исключение, извещающее о нестыковках.

        Если транспорт отрабатывает правильно, то метод завершается без
        исключений. Иначе генерируется исключение.

        """
        pass

    @throw_only(S3TransportError)
    def run_transfer(self, place):
        attempts = self.source.transport_attempts
        while True:
            try:
                return self.transfer(place)
            except:
                self._info("%s: transfer failed: %s/%s - %s s" % (
                    self.source.sourceId, attempts, self.source.transport_attempts, self.source.transport_sleep))
                attempts -= 1
                if attempts <= 0:
                    raise
                time.sleep(self.source.transport_sleep)

    def clean(self):
        """
        Транспорт должен запоминать ресурсы, которые занял. При вызове метода
        clean занятые ресурсы освобождаются.
        """
        pass

    def transfer_and_clean(self, place):
        """
        Вспомогательная функция. В 99% случаев должна отрабатывать без ошибок.
        """
        self.transfer(place)
        self.clean()
