#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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
#
#     http://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.
#

""" User application command runner """
import logging
import os
import platform
import sys
from typing import List

from skywalking.bootstrap import cli_logger
from skywalking.bootstrap.cli import SWRunnerFailure


def prefork_handler(command: List[str]) -> None:
    """
    This handles the cases where pre-forking servers are EXPLICITLY used:
    - gunicorn
    - uwsgi
    This handler only covers many plain usages, there could be cases where
    gunicorn/uwsgi is loaded by other scripts and the envvars used here
    are lost in such flow. (Aka. not covered by this handler)
    """
    os.environ['prefork'] = ''
    if command[0] == 'gunicorn':
        # Maybe should also check 1: since there could be a command before gunicorn
        cli_logger.info('We noticed you are using Gunicorn, '
                        'agent will automatically start the SkyWalking Python Agent '
                        'in all child (worker) processes; the master is instrumented only.')
        os.environ['prefork'] = 'gunicorn'
    elif command[0] == 'uwsgi':
        cli_logger.info('We noticed you are using uWSGI, '
                        'agent will automatically add the following '
                        'environment variables to your uWSGI options (to ensure a functional Python agent): '
                        '--enable-threads --master. \n'
                        'We will also start the SkyWalking Python Agent in all child (worker) '
                        'processes except for the master.')

        if '--master' not in command[1:]:
            cli_logger.warning('No master process is specified, '
                               'agent will not start properly in workers, '
                               'automatically adding --master to your uwsgi command.')
            os.environ['UWSGI_MASTER'] = 'true'

        if '--enable-threads' not in command[1:]:
            ...
            cli_logger.warning('No --enable-threads is specified, '
                               'agent will not start properly in workers, '
                               'automatically adding --enable-threads to your uwsgi command.')
            os.environ['UWSGI_ENABLE_THREADS'] = 'true'

        # this sets the option --import to our custom uwsgidecorator.postfork() function
        # which is in loader/uw.py
        os.environ['prefork'] = 'uwsgi'

        # let's hope no one uses up all 4 env variables, shared-python-import
        # shared-import, shared-pyimport, shared-py-import all imports in all processes no matter lazy/lazy-apps
        def pick_env_var():
            for env_var in ['UWSGI_SHARED_PYTHON_IMPORT',
                            'UWSGI_SHARED_IMPORT',
                            'UWSGI_SHARED_PYIMPORT',
                            'UWSGI_SHARED_PY_IMPORT']:
                if env_var not in os.environ:
                    return env_var
            raise SWRunnerFailure('No available env variable slot for sw-python to inject postfork hook, '
                                  'agent will not start properly in workers, please unset one of your env variables or '
                                  'fall back to manual postfork hook with @postfork.')

        os.environ[pick_env_var()] = 'uwsgi_hook'


def execute(command: List[str], experimental_check_prefork: bool) -> None:
    """ Set up environ and invokes the given command to replace current process """

    cli_logger.debug(f'SkyWalking Python agent `runner` received command {command}')

    if experimental_check_prefork:
        cli_logger.info('Detected experimental prefork support flag, checking for pre-forking servers...')
        prefork_handler(command=command)

    cli_logger.debug('Adding sitecustomize.py to PYTHONPATH')

    from skywalking.bootstrap.loader import __file__ as loader_dir
    from skywalking.bootstrap.hooks import __file__ as hook_dir
    loader_path = os.path.dirname(loader_dir)
    hook_path = os.path.dirname(hook_dir)

    new_path: str = ''
    python_path = os.environ.get('PYTHONPATH')
    if python_path:  # If there is already a different PYTHONPATH, PREPEND to it as we must get loaded first.
        partitioned = python_path.split(os.path.pathsep)
        if loader_path not in partitioned:  # check if we are already there
            new_path = os.path.pathsep.join([loader_path, hook_path, python_path])

    # When constructing sys.path PYTHONPATH is always
    # before other paths and after interpreter invoker path, which is here or none
    os.environ['PYTHONPATH'] = new_path if new_path else os.path.pathsep.join([loader_path, hook_path])
    cli_logger.debug(f"Updated PYTHONPATH - {os.environ['PYTHONPATH']}")

    # Used in sitecustomize to compare command's Python installation with CLI
    # If not match, need to stop agent from loading, and kill the process
    os.environ['SW_PYTHON_PREFIX'] = os.path.realpath(os.path.normpath(sys.prefix))
    os.environ['SW_PYTHON_VERSION'] = platform.python_version()

    # Pass down the logger debug setting to the replaced process, need a new logger there
    os.environ['SW_AGENT_SW_PYTHON_CLI_DEBUG_ENABLED'] = 'True' if cli_logger.level == logging.DEBUG else 'False'

    try:
        cli_logger.info(f'New process starting with command - `{command[0]}` args - `{command}`')
        os.execvp(command[0], command)
    except OSError:
        raise SWRunnerFailure
