# Copyright 2022 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.
# pylint: disable=line-too-long
"""Pigweed shell activation script.

This script can be used in three ways:

1. Activate the Pigweed environment in your current shell (i.e., modify your
   interactive shell's environment with Pigweed environment variables).

   Using bash (assuming a global Python 3 is in $PATH):
       source <(python3 ./pw_ide/activate.py -s bash)

   Using bash (using the environment Python):
       source <({environment}/pigweed-venv/bin/python ./pw_ide/activate.py -s bash)

2. Run a shell command or executable in an activated shell (i.e. apply a
   modified environment to a subprocess without affecting your current
   interactive shell).

    Example (assuming a global Python 3 is in $PATH):
        python3 ./pw_ide/activate.py -x 'pw ide cpp --list'

    Example (using the environment Python):
        {environment}/pigweed-venv/bin/python ./pw_ide/activate.py -x 'pw ide cpp --list'

    Example (using the environment Python on Windows):
        {environment}/pigweed-venv/Scripts/pythonw.exe ./pw_ide/activate.py -x 'pw ide cpp --list'

3. Produce a JSON representation of the Pigweed activated environment (-O) or
   the diff against your current environment that produces an activated
   environment (-o). See the help for more detailed information on the options
   available.

    Example (assuming a global Python 3 is in $PATH):
        python3 ./pw_ide/activate.py -o

    Example (using the environment Python):
        {environment}/pigweed-venv/bin/python ./pw_ide/activate.py -o

    Example (using the environment Python on Windows):
        {environment}/pigweed-venv/Scripts/pythonw.exe ./pw_ide/activate.py -o
"""
# pylint: enable=line-too-long

from abc import abstractmethod, ABC
import argparse
from inspect import cleandoc
import json
import os
from pathlib import Path
import shlex
import subprocess
import sys
from typing import Dict, Optional

# This expects this file to be in the Python module. If it ever moves
# (e.g. to the root of the repository), this will need to change.
PW_PROJECT_PATH = Path(
    os.environ.get('PW_PROJECT_ROOT',
                   os.environ.get('PW_ROOT',
                                  Path(__file__).parents[3])))


def _assumed_environment_root() -> Optional[Path]:
    actual_environment_root = os.environ.get('_PW_ACTUAL_ENVIRONMENT_ROOT')
    if actual_environment_root is not None and (
            root_path := Path(actual_environment_root)).exists():
        return root_path.absolute()

    default_environment = PW_PROJECT_PATH / 'environment'
    if default_environment.exists():
        return default_environment.absolute()

    default_dot_environment = PW_PROJECT_PATH / '.environment'
    if default_dot_environment.exists():
        return default_dot_environment.absolute()

    return None


class ShellModifier(ABC):
    """Abstract class for shell modifiers.

    A shell modifier provides an interface for modifying the environment
    variables in various shells. You can pass in a current environment state
    as a dictionary during instantiation and modify it and/or modify shell state
    through other side effects.
    """
    separator = ':'
    comment = '# '

    def __init__(self,
                 env: Optional[Dict[str, str]] = None,
                 env_only: bool = False,
                 path_var: str = '$PATH',
                 project_root: str = '.',
                 user_home: str = '~'):
        # Will contain the existing environment, but modified.
        self.env: Dict[str, str] = env if env is not None else {}

        # Will contain only the modifications to the environment, but not any
        # part of the existing environment.
        self.env_mod = {'PATH': path_var}

        # Will contain the side effects, i.e. commands executed in the shell to
        # modify its environment.
        self.side_effects = ''

        # Set this to not do any side effects, but just modify the environment
        # stored in this class.
        self.env_only = env_only

        self.project_root = project_root
        self.user_home = user_home

    def do_effect(self, effect: str):
        """Add to the commands that will affect the shell's environment.

        This is a no-op if the shell modifier is set to only store shell
        modification data rather than doing the side effects.
        """
        if not self.env_only:
            self.side_effects += f'{effect}\n'

    @abstractmethod
    def set_variable(self, var_name: str, value: str) -> None:
        pass

    @abstractmethod
    def prepend_variable(self, var_name: str, value: str) -> None:
        pass

    @abstractmethod
    def append_variable(self, var_name: str, value: str) -> None:
        pass


class BashShellModifier(ShellModifier):
    """Shell modifier for bash."""
    def set_variable(self, var_name: str, value: str):
        self.env[var_name] = value
        self.env_mod[var_name] = value
        quoted_value = shlex.quote(value)
        self.do_effect(f'export {var_name}={quoted_value}')

    def prepend_variable(self, var_name: str, value: str) -> None:
        self.env[var_name] = f'{value}{self.separator}{self.env[var_name]}'
        self.env_mod[
            var_name] = f'{value}{self.separator}{self.env_mod[var_name]}'
        quoted_value = shlex.quote(value)
        self.do_effect(
            f'export {var_name}={quoted_value}{self.separator}${var_name}')

    def append_variable(self, var_name: str, value: str) -> None:
        self.env[var_name] = f'{self.env[var_name]}{self.separator}{value}'
        self.env_mod[
            var_name] = f'{self.env_mod[var_name]}{self.separator}{value}'
        quoted_value = shlex.quote(value)
        self.do_effect(
            f'export {var_name}=${var_name}{self.separator}{quoted_value}')


def _sanitize_path(path: str, project_root_prefix: str,
                   user_home_prefix: str) -> str:
    """Given a path, return a sanitized path.

    By default, environment variable paths are usually absolute. If we want
    those paths to work across multiple systems, we need to sanitize them. This
    takes a string that may be a path, and if it is indeed a path, it returns
    the sanitized path, which is relative to either the repository root or the
    user's home directory. If it's not a path, it just returns the input.

    You can provide the strings that should be substituted for the project root
    and the user's home directory. This may be useful for applications that have
    their own way of representing those directories.

    Note that this is intended to work on Pigweed environment variables, which
    should all be relative to either of those two locations. Paths that aren't
    (e.g. the path to a system binary) won't really be sanitized.
    """
    # Return the argument if it's not actually a path.
    # This strategy relies on the fact that env_setup outputs absolute paths for
    # all path env vars. So if we get a variable that's not an absolute path, it
    # must not be a path at all.
    if not Path(path).is_absolute():
        return path

    project_root = PW_PROJECT_PATH.resolve()
    user_home = Path.home().resolve()
    resolved_path = Path(path).resolve()

    # TODO(b/248257406) Remove once we drop support for Python 3.8.
    def is_relative_to(path: Path, other: Path) -> bool:
        try:
            path.relative_to(other)
            return True
        except ValueError:
            return False

    if is_relative_to(resolved_path, project_root):
        return (f'{project_root_prefix}/' +
                str(resolved_path.relative_to(project_root)))

    if is_relative_to(resolved_path, user_home):
        return (f'{user_home_prefix}/' +
                str(resolved_path.relative_to(user_home)))

    # Path is not in the project root or user home, so just return it as is.
    return path


def _modify_env(file_path: Path,
                shell_modifier: ShellModifier,
                sanitize: bool = False) -> ShellModifier:
    """Modify the current shell state per the actions.json file provided."""
    # Load actions.json
    json_file_options = {}
    try:
        with file_path.open('r') as json_file:
            json_file_options = json.loads(json_file.read())
    except (FileNotFoundError, json.JSONDecodeError):
        sys.stderr.write('Unable to read file: {}\n'
                         'Please run this in bash or zsh:\n'
                         '  . ./bootstrap.sh\n'.format(file_path.as_posix()))

    root = shell_modifier.project_root
    home = shell_modifier.user_home

    # Set env vars
    for var_name, value in json_file_options['set'].items():
        if value is not None:
            value = _sanitize_path(value, root, home) if sanitize else value
            shell_modifier.set_variable(var_name, value)

    # Prepend & append env vars
    for var_name, mode_changes in json_file_options['modify'].items():
        for mode_name, values in mode_changes.items():
            if mode_name in ['prepend', 'append']:
                modify_variable = shell_modifier.prepend_variable

                if mode_name == 'append':
                    modify_variable = shell_modifier.append_variable

                for value in values:
                    value = _sanitize_path(value, root,
                                           home) if sanitize else value
                    modify_variable(var_name, value)

    return shell_modifier


def _build_argument_parser() -> argparse.ArgumentParser:
    """Set up `argparse`."""
    doc = __doc__

    if (env_root := _assumed_environment_root()) is not None:
        doc = doc.replace('{environment}',
                          str(env_root.relative_to(Path.cwd())))

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=doc,
    )

    config_file_dir = _assumed_environment_root()

    if config_file_dir is None:
        print('Environment directory not found!')
        print('This must be run from a bootstrapped Pigweed '
              'project directory.')
        sys.exit(1)

    config_file_path = config_file_dir / 'actions.json'

    if not config_file_path.exists():
        print(f'File not found! {config_file_path}')
        print('This must be run from a bootstrapped Pigweed '
              'project directory.')
        sys.exit(1)

    parser.add_argument('-c',
                        '--config-file',
                        default=config_file_path.as_posix(),
                        help='Path to actions.json config file, which defines '
                        'the modifications to the shell environment '
                        'needed to activate Pigweed. '
                        f'Default: {config_file_path.relative_to(Path.cwd())}')

    default_shell = Path(os.environ['SHELL']).name
    parser.add_argument('-s',
                        '--shell-mode',
                        default=default_shell,
                        help='Which shell is being used. '
                        f'Default: {default_shell}')

    parser.add_argument('-o',
                        '--out',
                        action='store_true',
                        help='Write only the modifications to the environment '
                        'out to JSON.')

    parser.add_argument('-O',
                        '--out-all',
                        action='store_true',
                        help='Write the complete modified environment to '
                        'JSON.')

    parser.add_argument(
        '-n',
        '--sanitize',
        action='store_true',
        help='Sanitize paths that are relative to the repo '
        'root or user home directory so that they are portable '
        'to other workstations.')

    parser.add_argument(
        '--path-var',
        default='$PATH',
        help='The string to substitute for the existing $PATH. Default: $PATH')

    parser.add_argument(
        '--project-root',
        default='.',
        help='The string to substitute for the project root when sanitizing '
        'paths. Default: .')

    parser.add_argument(
        '--user-home',
        default='~',
        help='The string to substitute for the user\'s home when sanitizing '
        'paths. Default: ~')

    parser.add_argument('-x',
                        '--exec',
                        help='A command to execute in the activated shell.',
                        metavar='COMMAND')

    return parser


def main() -> int:
    """The main CLI script."""
    args, _unused_extra_args = _build_argument_parser().parse_known_args()
    env = os.environ.copy()
    file_path = Path(args.config_file).absolute()

    # If we're executing a command in a subprocess, don't modify the current
    # shell's state. Instead, apply the modified state to the subprocess.
    env_only = args.exec is not None

    # Assume bash by default.
    shell_modifier = BashShellModifier

    # TODO(chadnorvell): if args.shell_mode == 'zsh', 'ksh', 'fish'...
    modified_env = _modify_env(
        file_path,
        shell_modifier(env=env,
                       env_only=env_only,
                       path_var=args.path_var,
                       project_root=args.project_root,
                       user_home=args.user_home), args.sanitize)

    if args.out_all:
        print(json.dumps(modified_env.env, sort_keys=True, indent=2))
        return 0

    if args.out:
        print(json.dumps(modified_env.env_mod, sort_keys=True, indent=2))
        return 0

    if args.exec is not None:
        # We're executing a command in a subprocess with the modified env.
        return subprocess.run(args.exec, env=modified_env.env,
                              shell=True).returncode

    # If we got here, we're trying to modify the current shell's env.
    print(modified_env.side_effects)

    # Let's warn the user if the output is going to stdout instead of being
    # executed by the shell.
    python_path = Path(sys.executable).relative_to(os.getcwd())
    c = shell_modifier.comment  # pylint: disable=invalid-name
    print(
        cleandoc(f"""
        {c}
        {c}Can you see these commands? If so, you probably wanted to
        {c}source this script instead of running it. Try this instead:
        {c}
        {c}    . <({str(python_path)} {' '.join(sys.argv)})
        {c}
        {c}Run this script with `-h` for more help."""))
    return 0


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