#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import logging
import os

import yaml

from liminal.build.image_builder import ImageBuilder, ServiceImageBuilderMixin
from liminal.core.util import files_util, class_util


def build_liminal_apps(path):
    """
    Build images for liminal apps in path.
    """
    config_files = files_util.find_config_files(path)

    for config_file in config_files:
        logging.info(f'Building artifacts for file: {config_file}')

        base_path = os.path.dirname(config_file)

        with open(config_file) as stream:
            liminal_config = yaml.safe_load(stream)

            if 'pipelines' in liminal_config:
                for pipeline in liminal_config['pipelines']:
                    for task in pipeline['tasks']:
                        task_name = task['task']

                        if 'source' in task:
                            task_type = task['type']
                            builder_class = __get_task_build_class(task_type)
                            if builder_class:
                                __build_image(base_path, task, builder_class)
                            else:
                                raise ValueError(f'No such task type: {task_type}')
                        else:
                            logging.info(
                                f'No source configured for task {task_name}, skipping build..')

            if 'services' in liminal_config:
                for service in liminal_config['services']:
                    service_type = service['type']
                    builder_class = __get_service_build_class(service_type)
                    if builder_class:
                        __build_image(base_path, service, builder_class)
                    else:
                        raise ValueError(f'No such service type: {service_type}')


def __build_image(base_path, builder_config, builder):
    if 'source' in builder_config:
        builder_instance = builder(
            config=builder_config,
            base_path=base_path,
            relative_source_path=builder_config['source'],
            tag=builder_config['image'])
        builder_instance.build()
    else:
        logging.info(f"No source provided for {builder_config['name']}, skipping.")


def __get_task_build_class(task_type):
    return task_build_types.get(task_type, None)


def __get_service_build_class(service_type):
    return service_build_types.get(service_type, None)


logging.info(f'Loading image builder implementations..')

# TODO: add configuration for user image builders package
image_builders_package = 'liminal.build.image'
# user_image_builders_package = 'TODO: user_image_builders_package'

TASK_BUILD_CLASSES = class_util.find_subclasses_in_packages(
    [image_builders_package],
    ImageBuilder)


def get_types_dict(task_build_classes):
    # take module name from class name
    return {x.split(".")[-2]: c for x, c in task_build_classes.items()}


task_build_types = get_types_dict(TASK_BUILD_CLASSES)

logging.info(f'Finished loading image builder implementations: {TASK_BUILD_CLASSES}')
logging.info(f'Loading service image builder implementations..')

# TODO: add configuration for user service image builders package
service_builders_package = 'liminal.build.service'
# user_service_builders_package = 'TODO: user_service_builders_package'

service_build_classes = class_util.find_subclasses_in_packages(
    [service_builders_package],
    ServiceImageBuilderMixin)

service_build_types = get_types_dict(service_build_classes)
logging.info(f'Finished loading service image builder implementations: {service_build_classes}')
