# Copyright 2021 The Pigweed 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
#
#     https://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.
"""Outputs the contents of blobs as a hard-coded arrays in a C++ library."""

import argparse
import itertools
import json
from pathlib import Path
from string import Template
import textwrap
from typing import (Any, Generator, Iterable, NamedTuple, Optional, Sequence,
                    Tuple)

COMMENT = f"""\
// This file was generated by {Path(__file__).name}.
//
// DO NOT EDIT!
//
// This file contains declarations for byte arrays created from files during the
// build. The byte arrays are constant initialized and are safe to access at any
// time, including before main().
//
// See https://pigweed.dev/pw_build/#pw-cc-blob-library for details.
"""

HEADER_PREFIX = COMMENT + textwrap.dedent("""\
    #pragma once

    #include <array>
    #include <cstddef>

    """)

SOURCE_PREFIX_TEMPLATE = Template(COMMENT + textwrap.dedent("""\

        #include "$header_path"

        #include <array>
        #include <cstddef>

        #include "pw_preprocessor/compiler.h"

        """))

NAMESPACE_OPEN_TEMPLATE = Template('namespace ${namespace} {\n')

NAMESPACE_CLOSE_TEMPLATE = Template('\n}  // namespace ${namespace}\n')

BLOB_DECLARATION_TEMPLATE = Template(
    '\nextern const std::array<std::byte, ${size_bytes}> ${symbol_name};\n')

LINKER_SECTION_TEMPLATE = Template(
    'PW_PLACE_IN_SECTION("${linker_section}")\n')

BLOB_DEFINITION_MULTI_LINE = Template(
    '\n${section_attr}'
    '${alignas}constexpr std::array<std::byte, ${size_bytes}> ${symbol_name}'
    ' = {\n${bytes_lines}\n};\n')

BYTES_PER_LINE = 4


class Blob(NamedTuple):
    symbol_name: str
    file_path: Path
    linker_section: Optional[str]
    alignas: Optional[str] = None

    @staticmethod
    def from_dict(blob_dict: dict) -> 'Blob':
        return Blob(blob_dict['symbol_name'], Path(blob_dict['file_path']),
                    blob_dict.get('linker_section'), blob_dict.get('alignas'))


def parse_args() -> dict:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--blob-file',
                        type=Path,
                        required=True,
                        help=('Path to json file containing the list of blobs '
                              'to generate.'))
    parser.add_argument('--header-include',
                        required=True,
                        help='Path to use in #includes for the header')
    parser.add_argument('--out-source',
                        type=Path,
                        required=True,
                        help='Path at which to write .cpp file')
    parser.add_argument('--out-header',
                        type=Path,
                        required=True,
                        help='Path at which to write .h file')
    parser.add_argument('--namespace',
                        type=str,
                        required=False,
                        help=('Optional namespace that blobs will be scoped'
                              'within.'))

    return vars(parser.parse_args())


def split_into_chunks(
        data: Iterable[Any],
        chunk_size: int) -> Generator[Tuple[Any, ...], None, None]:
    """Splits an iterable into chunks of a given size."""
    data_iterator = iter(data)
    chunk = tuple(itertools.islice(data_iterator, chunk_size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(data_iterator, chunk_size))


def header_from_blobs(blobs: Iterable[Blob],
                      namespace: Optional[str] = None) -> str:
    """Generate the contents of a C++ header file from blobs."""
    lines = [HEADER_PREFIX]
    if namespace:
        lines.append(NAMESPACE_OPEN_TEMPLATE.substitute(namespace=namespace))
    for blob in blobs:
        data = blob.file_path.read_bytes()
        lines.append(
            BLOB_DECLARATION_TEMPLATE.substitute(symbol_name=blob.symbol_name,
                                                 size_bytes=len(data)))
    if namespace:
        lines.append(NAMESPACE_CLOSE_TEMPLATE.substitute(namespace=namespace))

    return ''.join(lines)


def array_def_from_blob_data(blob: Blob, blob_data: bytes) -> str:
    """Generates an array definition for the given blob data."""
    if blob.linker_section:
        section_attr = LINKER_SECTION_TEMPLATE.substitute(
            linker_section=blob.linker_section)
    else:
        section_attr = ''

    byte_strs = ['std::byte{{0x{:02X}}}'.format(b) for b in blob_data]

    lines = []
    for byte_strs_for_line in split_into_chunks(byte_strs, BYTES_PER_LINE):
        bytes_segment = ', '.join(byte_strs_for_line)
        lines.append(f'    {bytes_segment},')

    return BLOB_DEFINITION_MULTI_LINE.substitute(
        section_attr=section_attr,
        alignas=f'alignas({blob.alignas}) ' if blob.alignas else '',
        symbol_name=blob.symbol_name,
        size_bytes=len(blob_data),
        bytes_lines='\n'.join(lines))


def source_from_blobs(blobs: Iterable[Blob],
                      header_path: str,
                      namespace: Optional[str] = None) -> str:
    """Generate the contents of a C++ source file from blobs."""
    lines = [SOURCE_PREFIX_TEMPLATE.substitute(header_path=header_path)]
    if namespace:
        lines.append(NAMESPACE_OPEN_TEMPLATE.substitute(namespace=namespace))
    for blob in blobs:
        data = blob.file_path.read_bytes()
        lines.append(array_def_from_blob_data(blob, data))
    if namespace:
        lines.append(NAMESPACE_CLOSE_TEMPLATE.substitute(namespace=namespace))

    return ''.join(lines)


def load_blobs(blob_file: Path) -> Sequence[Blob]:
    with blob_file.open() as blob_fp:
        return [Blob.from_dict(blob) for blob in json.load(blob_fp)]


def main(blob_file: Path,
         header_include: str,
         out_source: Path,
         out_header: Path,
         namespace: Optional[str] = None) -> None:
    blobs = load_blobs(blob_file)

    out_header.parent.mkdir(parents=True, exist_ok=True)
    out_header.write_text(header_from_blobs(blobs, namespace))

    out_source.parent.mkdir(parents=True, exist_ok=True)
    out_source.write_text(source_from_blobs(blobs, header_include, namespace))


if __name__ == '__main__':
    main(**parse_args())
