# Copyright (c) 2021 Project CHIP Authors
#
# 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 shutil
import tarfile
from abc import ABC, abstractmethod
from dataclasses import dataclass


@dataclass
class BuilderOptions:
    # Generate a link map file
    enable_link_map_file: bool = False

    # Enable flashbundle generation stage
    enable_flashbundle: bool = False

    # Allow to wrap default build command
    pw_command_launcher: str = None

    # Locations where files are pre-generated
    pregen_dir: str = None


@dataclass
class BuilderOutput:
    source: str  # Source file generated by the build
    target: str  # Target file to be copied to


class Builder(ABC):
    """Generic builder base class for CHIP.

    Provides ability to bootstrap and copy output artifacts and subclasses can
    use a generic shell runner.

    """

    def __init__(self, root, runner):
        self.root = os.path.abspath(root)
        self._runner = runner

        # Set post-init once actual build target is known
        self.identifier = None
        self.output_dir = None
        self.options = BuilderOptions()

    @abstractmethod
    def generate(self):
        """Generate the build files - generally the ninja/makefiles"""
        raise NotImplementedError()

    @abstractmethod
    def _build(self):
        """Perform an actual build"""
        raise NotImplementedError()

    def _bundle(self):
        """Perform an actual generating of flashbundle.

           May do nothing (and builder can choose not to implement this) if
           the app does not need special steps for generating flashbundle (e.g.
           on Linux platform, the output ELF files can be used directly).
        """
        pass

    @abstractmethod
    def build_outputs(self):
        """Return a list of relevant BuilderOutput objects after a build.

           May use build output data (e.g. manifests), so this should be
           invoked only after a build has succeeded.
        """
        raise NotImplementedError()

    def bundle_outputs(self):
        """Return the BuilderOutput objects in flashbundle.

           Return an empty list (and builder can choose not to implement this)
           if the app does not need special files as flashbundle.

           May use data from _bundle(), so this should be invoked only after
           _bundle() has succeeded.
        """
        return []

    def outputs(self):
        outputs = list(self.build_outputs())
        if self.options.enable_flashbundle:
            outputs.extend(self.bundle_outputs())
        return outputs

    def build(self):
        self._build()
        if self.options.enable_flashbundle:
            self._bundle()

    def _Execute(self, cmdarray, title=None):
        self._runner.Run(cmdarray, title=title)

    def CompressArtifacts(self, target_file: str):
        with tarfile.open(target_file, "w:gz") as tar:
            for output in self.outputs():
                logging.info('Adding %s into %s(%s)',
                             output.source, target_file, output.target)
                tar.add(output.source, output.target)

    def CopyArtifacts(self, target_dir: str):
        for output in self.outputs():
            logging.info(f'Copying {output.source} into {output.target}')

            target_full_name = os.path.join(target_dir, output.target)
            target_dir_full_name = os.path.dirname(target_full_name)

            if not os.path.exists(target_dir_full_name):
                logging.info('Creating subdirectory %s first',
                             target_dir_full_name)
                os.makedirs(target_dir_full_name)

            shutil.copyfile(output.source, target_full_name)
            shutil.copymode(output.source, target_full_name)
