# Licensed 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}')
