"""Module for the asteex runner."""

import logging
import asyncio


class Runner:
    """Class for the runner."""

    def __init__(self, generator, executor, reporter):
        self.__generator = generator
        self.__executor = executor
        self.__reporter = reporter

    def run(self):
        """Perform the execution."""
        asyncio.run(self.arrange())

    async def arrange(self):
        """Arrange the execution so that it can be run."""
        logger = logging.getLogger(__name__)
        logger.debug("Try to perform a new test run.")

        logger.debug("Try to arrange test instances.")
        try:
            instances = self.__generator.generate()
        except Exception as error:
            logger.exception("Failed to arrange test instances.")
            raise RunError("Failed to arrange test instances") from error

        logger.debug("Arranged test instances.")

        logger.debug("Try to arrange test results.")
        try:
            results = self.__executor.execute(instances)
        except Exception as error:
            logger.exception("Failed to arrange test results.")
            raise RunError("Failed to arrange test results") from error

        logger.debug("Arranged test results.")

        logger.debug("Try to report test results.")
        try:
            await self.__reporter.report(results)
        except Exception as error:
            logger.exception("Failed to report test results or await reporting.")
            raise RunError("Failed to report test results or await reporting") from error

        logger.debug("Reported test results.")

        logger.info("Finished the test run.")


class RunError(Exception):
    """Generic exception for the errors occured during test runs."""
