import logging

from du.gerrit.ssh.Connection import Connection

import du.gerrit.rest.Utils as GerritRestUtils
from du.gerrit.rest.change.ChangeEndpoint import ChangeEndpoint
from du.drepo.manifest.Remote import ProtocolType

from urllib.parse import urlparse
from urllib.parse import urlparse, urlunparse, quote

logger = logging.getLogger(__name__.split(".")[-1])


class Utils:
    """
    Collection of drepo utility functions
    """

    @staticmethod
    def createQueryConnection(remote, httpCredentials):
        """
        Create a query connection (HTTP or SSH) based on what's available in the given remote

        @param remote Remote
        @param httpCredentials A map of HTTP credentials
        """

        if remote.ssh:
            # Prioritize SSH if available
            return Connection(remote.ssh)

        elif remote.http:
            hostName = urlparse(remote.http).hostname

            username = None
            password = <PASSWORD>

            # Check if we have the credentials for this HTTP server
            if hostName in httpCredentials:
                username = httpCredentials[hostName].username
                password = httpCredentials[hostName].password

            # Create an endpoint
            return ChangeEndpoint(
                GerritRestUtils.getApi(username, password, remote.http)
            )

        raise RuntimeError("Neither SSH nor HTTP defined")

    @staticmethod
    def injectPassword(url, httpCredentials):
        """
        Inject a HTTP username/password into a git URL if possible

        Has no effect on non HTTP URLS

        @param url Fetch URL
        @return URL injected with username/password (e.g. http://username:password@server.com)

        """
        url = urlparse(url)

        # Only do this for HTTP URLs for which we have credentials
        if (
            url.scheme.startswith(ProtocolType.HTTP.value)
            and url.hostname in httpCredentials
        ):
            credentials = httpCredentials[url.hostname]

            # If username is defined via URL, it should match the one from the credentials
            if url.username and url.username != credentials.username:
                raise RuntimeError(
                    "Username mismatch: %r != %r" % (url.username, credentials.username)
                )

            encodedNetloc = url.netloc

            # Username prefix (e.g. user@)
            usernamePrefix = credentials.username + "@"

            if not encodedNetloc.startswith(usernamePrefix):
                # Prepend username
                encodedNetloc = usernamePrefix + encodedNetloc

            tokens = encodedNetloc.split("@")

            # Append password (percent encoded)
            encodedNetloc = (
                tokens[0] + ":" + quote(credentials.password, safe="") + "@" + tokens[1]
            )

            # Replace the netloc with the one encoded with a password
            url = url._replace(netloc=encodedNetloc)

        return urlunparse(url)

import logging

from du.gerrit.ssh.Connection import Connection

import du.gerrit.rest.Utils as GerritRestUtils
from du.gerrit.rest.change.ChangeEndpoint import ChangeEndpoint
from du.drepo.manifest.Remote import ProtocolType

from urllib.parse import urlparse
from urllib.parse import urlparse, urlunparse, quote

logger = logging.getLogger(__name__.split(".")[-1])


class Utils:
    """
    Collection of drepo utility functions
    """

    @staticmethod
    def createQueryConnection(remote, httpCredentials):
        """
        Create a query connection (HTTP or SSH) based on what's available in the given remote

        @param remote Remote
        @param httpCredentials A map of HTTP credentials
        """

        if remote.ssh:
            # Prioritize SSH if available
            return Connection(remote.ssh)

        elif remote.http:
            hostName = urlparse(remote.http).hostname

            username = None
            password = <PASSWORD>

            # Check if we have the credentials for this HTTP server
            if hostName in httpCredentials:
                username = httpCredentials[hostName].username
                password = httpCredentials[hostName].password

            # Create an endpoint
            return ChangeEndpoint(
                GerritRestUtils.getApi(username, password, remote.http)
            )

        raise RuntimeError("Neither SSH nor HTTP defined")

    @staticmethod
    def injectPassword(url, httpCredentials):
        """
        Inject a HTTP username/password into a git URL if possible

        Has no effect on non HTTP URLS

        @param url Fetch URL
        @return URL injected with username/password (e.g. http://username:password@server.com)

        """
        url = urlparse(url)

        # Only do this for HTTP URLs for which we have credentials
        if (
            url.scheme.startswith(ProtocolType.HTTP.value)
            and url.hostname in httpCredentials
        ):
            credentials = httpCredentials[url.hostname]

            # If username is defined via URL, it should match the one from the credentials
            if url.username and url.username != credentials.username:
                raise RuntimeError(
                    "Username mismatch: %r != %r" % (url.username, credentials.username)
                )

            encodedNetloc = url.netloc

            # Username prefix (e.g. user@)
            usernamePrefix = credentials.username + "@"

            if not encodedNetloc.startswith(usernamePrefix):
                # Prepend username
                encodedNetloc = usernamePrefix + encodedNetloc

            tokens = encodedNetloc.split("@")

            # Append password (percent encoded)
            encodedNetloc = (
                tokens[0] + ":" + quote(credentials.password, safe="") + "@" + tokens[1]
            )

            # Replace the netloc with the one encoded with a password
            url = url._replace(netloc=encodedNetloc)

        return urlunparse(url)

Collection of drepo utility functions Create a query connection (HTTP or SSH) based on what's available in the given remote          @param remote Remote         @param httpCredentials A map of HTTP credentials # Prioritize SSH if available # Check if we have the credentials for this HTTP server # Create an endpoint Inject a HTTP username/password into a git URL if possible          Has no effect on non HTTP URLS          @param url Fetch URL         @return URL injected with username/password (e.g. http://username:password@server.com) # Only do this for HTTP URLs for which we have credentials # If username is defined via URL, it should match the one from the credentials # Username prefix (e.g. user@) # Prepend username # Append password (percent encoded) # Replace the netloc with the one encoded with a password