# 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, List, 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_pwpb_args(args: argparse.Namespace,
                     include_paths: List[str]) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--plugin',
        f'protoc-gen-custom={args.plugin_path}',
        f'--custom_opt=-I{args.compile_dir}',
        *[f'--custom_opt=-I{include_path}' for include_path in include_paths],
        '--custom_out',
        args.out_dir,
    )


def protoc_pwpb_rpc_args(args: argparse.Namespace,
                         _include_paths: List[str]) -> 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,
                   _include_paths: List[str]) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--go_out',
        f'plugins=grpc:{args.out_dir}',
    )


def protoc_nanopb_args(args: argparse.Namespace,
                       _include_paths: List[str]) -> 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,
                           _include_paths: List[str]) -> 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,
                        _include_paths: List[str]) -> 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,
                       _include_paths: List[str]) -> Tuple[str, ...]:
    return _COMMON_FLAGS + (
        '--python_out',
        args.out_dir,
        '--mypy_out',
        args.out_dir,
    )


_DefaultArgsFunction = Callable[[argparse.Namespace, List[str]], 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] = {
    'go': protoc_go_args,
    'nanopb': protoc_nanopb_args,
    'nanopb_rpc': protoc_nanopb_rpc_args,
    'pwpb': protoc_pwpb_args,
    'pwpb_rpc': protoc_pwpb_rpc_args,
    'python': protoc_python_args,
    'raw_rpc': protoc_raw_rpc_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: List[str] = []
    if args.include_file:
        include_paths = [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}',
        *[f'-I{include_path}' for include_path in include_paths],
        *DEFAULT_PROTOC_ARGS[args.language](args, include_paths),
        *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())
