# Copyright 2019 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.
"""Renders HTML documentation using Sphinx."""

# TODO(frolv): Figure out a solution for installing all library dependencies
# to run Sphinx and build RTD docs.

import argparse
import collections
import json
import os
import shutil
import subprocess
import sys

from typing import Dict, List, Tuple

SCRIPT_HEADER: str = '''
██████╗ ██╗ ██████╗ ██╗    ██╗███████╗███████╗██████╗     ██████╗  ██████╗  ██████╗███████╗
██╔══██╗██║██╔════╝ ██║    ██║██╔════╝██╔════╝██╔══██╗    ██╔══██╗██╔═══██╗██╔════╝██╔════╝
██████╔╝██║██║  ███╗██║ █╗ ██║█████╗  █████╗  ██║  ██║    ██║  ██║██║   ██║██║     ███████╗
██╔═══╝ ██║██║   ██║██║███╗██║██╔══╝  ██╔══╝  ██║  ██║    ██║  ██║██║   ██║██║     ╚════██║
██║     ██║╚██████╔╝╚███╔███╔╝███████╗███████╗██████╔╝    ██████╔╝╚██████╔╝╚██████╗███████║
╚═╝     ╚═╝ ╚═════╝  ╚══╝╚══╝ ╚══════╝╚══════╝╚═════╝     ╚═════╝  ╚═════╝  ╚═════╝╚══════╝
'''


def parse_args() -> argparse.Namespace:
    """Parses command-line arguments."""

    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--sphinx-build-dir',
                        required=True,
                        help='Directory in which to build docs')
    parser.add_argument('--conf',
                        required=True,
                        help='Path to conf.py file for Sphinx')
    parser.add_argument('--gn-root',
                        required=True,
                        help='Root of the GN build tree')
    parser.add_argument('--gn-gen-root',
                        required=True,
                        help='Root of the GN gen tree')
    parser.add_argument('sources',
                        nargs='+',
                        help='Paths to the root level rst source files')
    parser.add_argument('--out-dir',
                        required=True,
                        help='Output directory for rendered HTML docs')
    parser.add_argument('--metadata',
                        required=True,
                        type=argparse.FileType('r'),
                        help='Metadata JSON file')
    return parser.parse_args()


def build_docs(src_dir: str, dst_dir: str) -> int:
    """Runs Sphinx to render HTML documentation from a doc tree."""

    # TODO(frolv): Specify the Sphinx script from a prebuilts path instead of
    # requiring it in the tree.
    command = [
        'sphinx-build', '-W', '-b', 'html', '-d', f'{dst_dir}/help', src_dir,
        f'{dst_dir}/html'
    ]
    return subprocess.call(command)


def mkdir(dirname: str, exist_ok: bool = False) -> None:
    """Wrapper around os.makedirs that prints the operation."""
    print(f'MKDIR {dirname}')
    os.makedirs(dirname, exist_ok=exist_ok)


def copy(src: str, dst: str) -> None:
    """Wrapper around shutil.copy that prints the operation."""
    print(f'COPY  {src} -> {dst}')
    shutil.copy(src, dst)


def copy_doc_tree(args: argparse.Namespace) -> None:
    """Copies doc source and input files into a build tree."""
    def build_path(path):
        """Converts a source path to a filename in the build directory."""
        if path.startswith(args.gn_root):
            path = os.path.relpath(path, args.gn_root)
        elif path.startswith(args.gn_gen_root):
            path = os.path.relpath(path, args.gn_gen_root)

        return os.path.join(args.sphinx_build_dir, path)

    source_files = json.load(args.metadata)
    copy_paths = [build_path(f) for f in source_files]

    mkdir(args.sphinx_build_dir)
    for source_path in args.sources:
        copy(source_path, f'{args.sphinx_build_dir}/')
    copy(args.conf, f'{args.sphinx_build_dir}/conf.py')

    # Map of directory path to list of source and destination file paths.
    dirs: Dict[str, List[Tuple[str, str]]] = collections.defaultdict(list)

    for source_file, copy_path in zip(source_files, copy_paths):
        dirname = os.path.dirname(copy_path)
        dirs[dirname].append((source_file, copy_path))

    for directory, file_pairs in dirs.items():
        mkdir(directory, exist_ok=True)
        for src, dst in file_pairs:
            copy(src, dst)


def main() -> int:
    """Script entry point."""

    args = parse_args()

    # Clear out any existing docs for the target.
    if os.path.exists(args.sphinx_build_dir):
        shutil.rmtree(args.sphinx_build_dir)

    # TODO(pwbug/164): Printing the header causes unicode problems on Windows.
    # Disabled for now; re-enable once the root issue is fixed.
    # print(SCRIPT_HEADER)
    copy_doc_tree(args)

    # Flush all script output before running Sphinx.
    print('-' * 80, flush=True)

    return build_docs(args.sphinx_build_dir, args.out_dir)


if __name__ == '__main__':
    sys.exit(main())
