#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#
"""This module groups factory like functions to dispatch builds steps according to the connector language."""

from __future__ import annotations

import anyio
from connector_ops.utils import ConnectorLanguage  # type: ignore
from pipelines.airbyte_ci.connectors.build_image.steps import (
    java_connectors,
    manifest_only_connectors,
    python_connectors,
)
from pipelines.airbyte_ci.connectors.build_image.steps.common import (
    LoadContainerToLocalDockerHost,
    StepStatus,
)
from pipelines.airbyte_ci.connectors.context import ConnectorContext
from pipelines.airbyte_ci.connectors.reports import ConnectorReport, Report
from pipelines.models.steps import StepResult


class NoBuildStepForLanguageError(Exception):
    pass


LANGUAGE_BUILD_CONNECTOR_MAPPING = {
    ConnectorLanguage.PYTHON: python_connectors.run_connector_build,
    ConnectorLanguage.LOW_CODE: python_connectors.run_connector_build,
    ConnectorLanguage.MANIFEST_ONLY: manifest_only_connectors.run_connector_build,
    ConnectorLanguage.JAVA: java_connectors.run_connector_build,
}


async def run_connector_build(context: ConnectorContext) -> StepResult:
    """Run a build pipeline for a single connector."""
    if context.connector.language not in LANGUAGE_BUILD_CONNECTOR_MAPPING:
        raise NoBuildStepForLanguageError(
            f"No build step for connector language {context.connector.language}."
        )
    return await LANGUAGE_BUILD_CONNECTOR_MAPPING[context.connector.language](context)


async def run_connector_build_pipeline(
    context: ConnectorContext, semaphore: anyio.Semaphore, image_tag: str
) -> Report:
    """Run a build pipeline for a single connector.

    Args:
        context (ConnectorContext): The initialized connector context.
        semaphore (anyio.Semaphore): The semaphore to use to limit the number of concurrent builds.
        image_tag (str): The tag to use for the built image.
    Returns:
        ConnectorReport: The reports holding builds results.
    """
    step_results = []
    async with semaphore, context:
        build_result = await run_connector_build(context)
        per_platform_built_containers = build_result.output
        step_results.append(build_result)
        if context.is_local and build_result.status is StepStatus.SUCCESS:
            load_image_result = await LoadContainerToLocalDockerHost(
                context, image_tag
            ).run(per_platform_built_containers)
            step_results.append(load_image_result)
        report = ConnectorReport(context, step_results, name="BUILD RESULTS")
        context.report = report
    return report
