# Copyright 2020 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.
"""Script that invokes protoc to generate code for .proto files."""

import argparse
import logging
import os
from pathlib import Path
import subprocess
import sys
import tempfile
from typing import Callable, Dict, Optional, Tuple, Union

# Make sure dependencies are optional, since this script may be run when
# installing Python package dependencies through GN.
try:
    from pw_cli.log import install as setup_logging
except ImportError:
    from logging import basicConfig as setup_logging  # type: ignore

_LOG = logging.getLogger(__name__)

_COMMON_FLAGS = ('--experimental_allow_proto3_optional', )


def _argument_parser() -> argparse.ArgumentParser:
    """Registers the script's arguments on an argument parser."""

    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('--language',
                        required=True,
                        choices=DEFAULT_PROTOC_ARGS,
                        help='Output language')
    parser.add_argument('--plugin-path',
                        type=Path,
                        help='Path to the protoc plugin')
    parser.add_argument('--include-file',
                        type=argparse.FileType('r'),
                        help='File containing additional protoc include paths')
    parser.add_argument('--out-dir',
                        type=Path,
                        required=True,
                        help='Output directory for generated code')
    parser.add_argument('--compile-dir',
                        type=Path,
                        required=True,
                        help='Root path for compilation')
    parser.add_argument('--sources',
                        type=Path,
                        nargs='+',
                        help='Input protobuf files')

    return parser


def protoc_cc_args(args: argparse.Namespace) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--plugin',
        f'protoc-gen-custom={args.plugin_path}',
        '--custom_out',
        args.out_dir,
    )


def protoc_go_args(args: argparse.Namespace) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--go_out',
        f'plugins=grpc:{args.out_dir}',
    )


def protoc_nanopb_args(args: argparse.Namespace) -> Tuple[str, ...]:
    # nanopb needs to know of the include path to parse *.options files
    return _COMMON_FLAGS + (
        '--plugin',
        f'protoc-gen-nanopb={args.plugin_path}',
        # nanopb_opt provides the flags to use for nanopb_out. Windows doesn't
        # like when you merge the two using the `flag,...:out` syntax. Use
        # Posix-style paths since backslashes on Windows are treated like
        # escape characters.
        f'--nanopb_opt=-I{args.compile_dir.as_posix()}',
        f'--nanopb_out={args.out_dir}',
    )


def protoc_nanopb_rpc_args(args: argparse.Namespace) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--plugin',
        f'protoc-gen-custom={args.plugin_path}',
        '--custom_out',
        args.out_dir,
    )


def protoc_raw_rpc_args(args: argparse.Namespace) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--plugin',
        f'protoc-gen-custom={args.plugin_path}',
        '--custom_out',
        args.out_dir,
    )


def protoc_python_args(args: argparse.Namespace) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--python_out',
        args.out_dir,
        '--mypy_out',
        args.out_dir,
    )


_DefaultArgsFunction = Callable[[argparse.Namespace], Tuple[str, ...]]

# Default additional protoc arguments for each supported language.
# TODO(frolv): Make these overridable with a command-line argument.
DEFAULT_PROTOC_ARGS: Dict[str, _DefaultArgsFunction] = {
    'pwpb': protoc_cc_args,
    'go': protoc_go_args,
    'nanopb': protoc_nanopb_args,
    'nanopb_rpc': protoc_nanopb_rpc_args,
    'raw_rpc': protoc_raw_rpc_args,
    'python': protoc_python_args,
}

# Languages that protoc internally supports.
BUILTIN_PROTOC_LANGS = ('go', 'python')


def main() -> int:
    """Runs protoc as configured by command-line arguments."""

    parser = _argument_parser()
    args = parser.parse_args()

    if args.plugin_path is None and args.language not in BUILTIN_PROTOC_LANGS:
        parser.error(
            f'--plugin-path is required for --language {args.language}')

    args.out_dir.mkdir(parents=True, exist_ok=True)

    include_paths = [f'-I{line.strip()}' for line in args.include_file]

    wrapper_script: Optional[Path] = None

    # On Windows, use a .bat version of the plugin if it exists or create a .bat
    # wrapper to use if none exists.
    if os.name == 'nt' and args.plugin_path:
        if args.plugin_path.with_suffix('.bat').exists():
            args.plugin_path = args.plugin_path.with_suffix('.bat')
            _LOG.debug('Using Batch plugin %s', args.plugin_path)
        else:
            with tempfile.NamedTemporaryFile('w', suffix='.bat',
                                             delete=False) as file:
                file.write(f'@echo off\npython {args.plugin_path.resolve()}\n')

            args.plugin_path = wrapper_script = Path(file.name)
            _LOG.debug('Using generated plugin wrapper %s', args.plugin_path)

    cmd: Tuple[Union[str, Path], ...] = (
        'protoc',
        f'-I{args.compile_dir}',
        *include_paths,
        *DEFAULT_PROTOC_ARGS[args.language](args),
        *args.sources,
    )

    try:
        process = subprocess.run(cmd,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
    finally:
        if wrapper_script:
            wrapper_script.unlink()

    if process.returncode != 0:
        _LOG.error('Protocol buffer compilation failed!\n%s',
                   ' '.join(str(c) for c in cmd))
        sys.stderr.buffer.write(process.stdout)
        sys.stderr.flush()

    return process.returncode


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