"""Contains the Command base classes that depend on PipSession.

The classes in this module are in a separate module so the commands not
needing download / PackageFinder capability don't unnecessarily import the
PackageFinder machinery and all its vendored dependencies, etc.
"""

import logging
import os
from functools import partial

from pip._internal.cli import cmdoptions
from pip._internal.cli.base_command import Command
from pip._internal.cli.command_context import CommandContextMixIn
from pip._internal.exceptions import CommandError, PreviousBuildDirError
from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.selection_prefs import SelectionPreferences
from pip._internal.network.download import Downloader
from pip._internal.network.session import PipSession
from pip._internal.operations.prepare import RequirementPreparer
from pip._internal.req.constructors import (
    install_req_from_editable,
    install_req_from_line,
    install_req_from_parsed_requirement,
    install_req_from_req_string,
)
from pip._internal.req.req_file import parse_requirements
from pip._internal.req.req_set import RequirementSet
from pip._internal.self_outdated_check import (
    make_link_collector,
    pip_self_version_check,
)
from pip._internal.utils.temp_dir import tempdir_kinds
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
    from optparse import Values
    from typing import Any, List, Optional, Tuple

    from pip._internal.cache import WheelCache
    from pip._internal.models.target_python import TargetPython
    from pip._internal.req.req_install import InstallRequirement
    from pip._internal.req.req_tracker import RequirementTracker
    from pip._internal.resolution.base import BaseResolver
    from pip._internal.utils.temp_dir import (
        TempDirectory,
        TempDirectoryTypeRegistry,
    )


logger = logging.getLogger(__name__)


class SessionCommandMixin(CommandContextMixIn):

    """
    A class mixin for command classes needing _build_session().
    """
    def __init__(self):
        # type: () -> None
        super(SessionCommandMixin, self).__init__()
        self._session = None  # Optional[PipSession]

    @classmethod
    def _get_index_urls(cls, options):
        # type: (Values) -> Optional[List[str]]
        """Return a list of index urls from user-provided options."""
        index_urls = []
        if not getattr(options, "no_index", False):
            url = getattr(options, "index_url", None)
            if url:
                index_urls.append(url)
        urls = getattr(options, "extra_index_urls", None)
        if urls:
            index_urls.extend(urls)
        # Return None rather than an empty list
        return index_urls or None

    def get_default_session(self, options):
        # type: (Values) -> PipSession
        """Get a default-managed session."""
        if self._session is None:
            self._session = self.enter_context(self._build_session(options))
            # there's no type annotation on requests.Session, so it's
            # automatically ContextManager[Any] and self._session becomes Any,
            # then https://github.com/python/mypy/issues/7696 kicks in
            assert self._session is not None
        return self._session

    def _build_session(self, options, retries=None, timeout=None):
        # type: (Values, Optional[int], Optional[int]) -> PipSession
        assert not options.cache_dir or os.path.isabs(options.cache_dir)
        session = PipSession(
            cache=(
                os.path.join(options.cache_dir, "http")
                if options.cache_dir else None
            ),
            retries=retries if retries is not None else options.retries,
            trusted_hosts=options.trusted_hosts,
            index_urls=self._get_index_urls(options),
        )

        # Handle custom ca-bundles from the user
        if options.cert:
            session.verify = options.cert

        # Handle SSL client certificate
        if options.client_cert:
            session.cert = options.client_cert

        # Handle timeouts
        if options.timeout or timeout:
            session.timeout = (
                timeout if timeout is not None else options.timeout
            )

        # Handle configured proxies
        if options.proxy:
            session.proxies = {
                "http": options.proxy,
                "https": options.proxy,
            }

        # Determine if we can prompt the user for authentication or not
        session.auth.prompting = not options.no_input

        return session


class IndexGroupCommand(Command, SessionCommandMixin):

    """
    Abstract base class for commands with the index_group options.

    This also corresponds to the commands that permit the pip version check.
    """

    def handle_pip_version_check(self, options):
        # type: (Values) -> None
        """
        Do the pip version check if not disabled.

        This overrides the default behavior of not doing the check.
        """
        # Make sure the index_group options are present.
        assert hasattr(options, 'no_index')

        if options.disable_pip_version_check or options.no_index:
            return

        # Otherwise, check if we're using the latest version of pip available.
        session = self._build_session(
            options,
            retries=0,
            timeout=min(5, options.timeout)
        )
        with session:
            pip_self_version_check(session, options)


KEEPABLE_TEMPDIR_TYPES = [
    tempdir_kinds.BUILD_ENV,
    tempdir_kinds.EPHEM_WHEEL_CACHE,
    tempdir_kinds.REQ_BUILD,
]


def with_cleanup(func):
    # type: (Any) -> Any
    """Decorator for common logic related to managing temporary
    directories.
    """
    def configure_tempdir_registry(registry):
        # type: (TempDirectoryTypeRegistry) -> None
        for t in KEEPABLE_TEMPDIR_TYPES:
            registry.set_delete(t, False)

    def wrapper(self, options, args):
        # type: (RequirementCommand, Values, List[Any]) -> Optional[int]
        assert self.tempdir_registry is not None
        if options.no_clean:
            configure_tempdir_registry(self.tempdir_registry)

        try:
            return func(self, options, args)
        except PreviousBuildDirError:
            # This kind of conflict can occur when the user passes an explicit
            # build directory with a pre-existing folder. In that case we do
            # not want to accidentally remove it.
            configure_tempdir_registry(self.tempdir_registry)
            raise

    return wrapper


class RequirementCommand(IndexGroupCommand):

    def __init__(self, *args, **kw):
        # type: (Any, Any) -> None
        super(RequirementCommand, self).__init__(*args, **kw)

        self.cmd_opts.add_option(cmdoptions.no_clean())

    @staticmethod
    def make_requirement_preparer(
        temp_build_dir,           # type: TempDirectory
        options,                  # type: Values
        req_tracker,              # type: RequirementTracker
        session,                  # type: PipSession
        finder,                   # type: PackageFinder
        use_user_site,            # type: bool
        download_dir=None,        # type: str
        wheel_download_dir=None,  # type: str
    ):
        # type: (...) -> RequirementPreparer
        """
        Create a RequirementPreparer instance for the given parameters.
        """
        downloader = Downloader(session, progress_bar=options.progress_bar)

        temp_build_dir_path = temp_build_dir.path
        assert temp_build_dir_path is not None

        return RequirementPreparer(
            build_dir=temp_build_dir_path,
            src_dir=options.src_dir,
            download_dir=download_dir,
            wheel_download_dir=wheel_download_dir,
            build_isolation=options.build_isolation,
            req_tracker=req_tracker,
            downloader=downloader,
            finder=finder,
            require_hashes=options.require_hashes,
            use_user_site=use_user_site,
        )

    @staticmethod
    def make_resolver(
        preparer,                            # type: RequirementPreparer
        finder,                              # type: PackageFinder
        options,                             # type: Values
        wheel_cache=None,                    # type: Optional[WheelCache]
        use_user_site=False,                 # type: bool
        ignore_installed=True,               # type: bool
        ignore_requires_python=False,        # type: bool
        force_reinstall=False,               # type: bool
        upgrade_strategy="to-satisfy-only",  # type: str
        use_pep517=None,                     # type: Optional[bool]
        py_version_info=None            # type: Optional[Tuple[int, ...]]
    ):
        # type: (...) -> BaseResolver
        """
        Create a Resolver instance for the given parameters.
        """
        make_install_req = partial(
            install_req_from_req_string,
            isolated=options.isolated_mode,
            use_pep517=use_pep517,
        )
        # The long import name and duplicated invocation is needed to convince
        # Mypy into correctly typechecking. Otherwise it would complain the
        # "Resolver" class being redefined.
        if 'resolver' in options.unstable_features:
            import pip._internal.resolution.resolvelib.resolver
            return pip._internal.resolution.resolvelib.resolver.Resolver(
                preparer=preparer,
                finder=finder,
                wheel_cache=wheel_cache,
                make_install_req=make_install_req,
                use_user_site=use_user_site,
                ignore_dependencies=options.ignore_dependencies,
                ignore_installed=ignore_installed,
                ignore_requires_python=ignore_requires_python,
                force_reinstall=force_reinstall,
                upgrade_strategy=upgrade_strategy,
                py_version_info=py_version_info,
            )
        import pip._internal.resolution.legacy.resolver
        return pip._internal.resolution.legacy.resolver.Resolver(
            preparer=preparer,
            finder=finder,
            wheel_cache=wheel_cache,
            make_install_req=make_install_req,
            use_user_site=use_user_site,
            ignore_dependencies=options.ignore_dependencies,
            ignore_installed=ignore_installed,
            ignore_requires_python=ignore_requires_python,
            force_reinstall=force_reinstall,
            upgrade_strategy=upgrade_strategy,
            py_version_info=py_version_info,
        )

    def get_requirements(
        self,
        args,             # type: List[str]
        options,          # type: Values
        finder,           # type: PackageFinder
        session,          # type: PipSession
        check_supported_wheels=True,  # type: bool
    ):
        # type: (...) -> List[InstallRequirement]
        """
        Parse command-line arguments into the corresponding requirements.
        """
        requirement_set = RequirementSet(
            check_supported_wheels=check_supported_wheels
        )
        for filename in options.constraints:
            for parsed_req in parse_requirements(
                    filename,
                    constraint=True, finder=finder, options=options,
                    session=session):
                req_to_add = install_req_from_parsed_requirement(
                    parsed_req,
                    isolated=options.isolated_mode,
                )
                req_to_add.is_direct = True
                requirement_set.add_requirement(req_to_add)

        for req in args:
            req_to_add = install_req_from_line(
                req, None, isolated=options.isolated_mode,
                use_pep517=options.use_pep517,
            )
            req_to_add.is_direct = True
            requirement_set.add_requirement(req_to_add)

        for req in options.editables:
            req_to_add = install_req_from_editable(
                req,
                isolated=options.isolated_mode,
                use_pep517=options.use_pep517,
            )
            req_to_add.is_direct = True
            requirement_set.add_requirement(req_to_add)

        # NOTE: options.require_hashes may be set if --require-hashes is True
        for filename in options.requirements:
            for parsed_req in parse_requirements(
                    filename,
                    finder=finder, options=options, session=session):
                req_to_add = install_req_from_parsed_requirement(
                    parsed_req,
                    isolated=options.isolated_mode,
                    use_pep517=options.use_pep517
                )
                req_to_add.is_direct = True
                requirement_set.add_requirement(req_to_add)

        # If any requirement has hash options, enable hash checking.
        requirements = requirement_set.all_requirements
        if any(req.has_hash_options for req in requirements):
            options.require_hashes = True

        if not (args or options.editables or options.requirements):
            opts = {'name': self.name}
            if options.find_links:
                raise CommandError(
                    'You must give at least one requirement to {name} '
                    '(maybe you meant "pip {name} {links}"?)'.format(
                        **dict(opts, links=' '.join(options.find_links))))
            else:
                raise CommandError(
                    'You must give at least one requirement to {name} '
                    '(see "pip help {name}")'.format(**opts))

        return requirements

    @staticmethod
    def trace_basic_info(finder):
        # type: (PackageFinder) -> None
        """
        Trace basic information about the provided objects.
        """
        # Display where finder is looking for packages
        search_scope = finder.search_scope
        locations = search_scope.get_formatted_locations()
        if locations:
            logger.info(locations)

    def _build_package_finder(
        self,
        options,               # type: Values
        session,               # type: PipSession
        target_python=None,    # type: Optional[TargetPython]
        ignore_requires_python=None,  # type: Optional[bool]
    ):
        # type: (...) -> PackageFinder
        """
        Create a package finder appropriate to this requirement command.

        :param ignore_requires_python: Whether to ignore incompatible
            "Requires-Python" values in links. Defaults to False.
        """
        link_collector = make_link_collector(session, options=options)
        selection_prefs = SelectionPreferences(
            allow_yanked=True,
            format_control=options.format_control,
            allow_all_prereleases=options.pre,
            prefer_binary=options.prefer_binary,
            ignore_requires_python=ignore_requires_python,
        )

        return PackageFinder.create(
            link_collector=link_collector,
            selection_prefs=selection_prefs,
            target_python=target_python,
        )
