from datetime import datetime

from application.interactor import LoaderUpdaterInteractor
from application.manager._UpdaterManager import UpdaterManager
from application.model import UpdateType
from application.model.configuration import Configurations
from application.model.customexception import NoUpdateFound
from application.repository.pos import (
    LoaderUpdaterPOSRepository,
    CatalogUpdaterPOSRepository,
    BinaryUpdaterPOSRepository,
)
from application.service import LoaderUpdaterService
from application.util import LoggerUtil

logger = LoggerUtil.get_logger_name(__name__)


class LoaderUpdaterManager(UpdaterManager):
    def __init__(
        self,
        configs,                    # type: Configurations
        interactor,                 # type: LoaderUpdaterInteractor
        pos_repository,             # type: LoaderUpdaterPOSRepository
        catalog_pos_repository,     # type: CatalogUpdaterPOSRepository
        binaries_repository,        # type: BinaryUpdaterPOSRepository
        loader_updater_service,     # type: LoaderUpdaterService
    ):
        # type: (...) -> None # noqa

        name = UpdateType.loader.name
        super(LoaderUpdaterManager, self).__init__(name, configs, interactor, pos_repository, logger)
        self.interactor = interactor
        self.catalog_pos_repository = catalog_pos_repository
        self.binaries_repository = binaries_repository
        self.pos_repository = pos_repository
        self.loader_updater_service = loader_updater_service

        self.logger = logger

        try:
            if pos_repository.get_pending_loader_update_id():
                self.update()
        except (Exception,):
            self.logger.exception("Error updating loader on manager")

    def update(self):
        # type: () -> None

        self.interactor.update_loaders()

    def has_update_to_apply(self):
        # type: () -> None

        if not self.binaries_repository.has_already_applied_update():
            raise NoUpdateFound()

        if not self.catalog_pos_repository.has_already_applied_update():
            raise NoUpdateFound()

        last_update_date = self.pos_repository.get_last_loader_update_date()
        today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
        update_to_apply = last_update_date is None or last_update_date < today
        if not update_to_apply:
            raise NoUpdateFound()

    def notify_pending_update(
        self,   # type: LoaderUpdaterManager
    ):
        # type: (...) -> None

        has_pending_loader_update = self.pos_repository.has_pending_loader_update()
        if not has_pending_loader_update:
            return

        last_loader_update = self.pos_repository.get_last_loader_update()
        if last_loader_update is None:
            return

        self.loader_updater_service.send_result_message(
            current_update_id=str(last_loader_update.update_id),
        )
