# Source code for selenium.webdriver.common.proxy

    # Licensed to the Software Freedom Conservancy (SFC) under one
    # or more contributor license agreements.  See the NOTICE file
    # distributed with this work for additional information
    # regarding copyright ownership.  The SFC 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.
    """The Proxy implementation."""

    class ProxyTypeFactory:
        """Factory for proxy types."""

        @staticmethod
        def make(ff_value, string):
            return {"ff_value": ff_value, "string": string}

    class ProxyType:
        """Set of possible types of proxy.

        Each proxy type has 2 properties:    'ff_value' is value of Firefox
        profile preference,    'string' is id of proxy type.
        """

        DIRECT = ProxyTypeFactory.make(0, "DIRECT")  # Direct connection, no proxy (default on Windows).
        MANUAL = ProxyTypeFactory.make(1, "MANUAL")  # Manual proxy settings (e.g., for httpProxy).
        PAC = ProxyTypeFactory.make(2, "PAC")  # Proxy autoconfiguration from URL.
        RESERVED_1 = ProxyTypeFactory.make(3, "RESERVED1")  # Never used.
        AUTODETECT = ProxyTypeFactory.make(4, "AUTODETECT")  # Proxy autodetection (presumably with WPAD).
        SYSTEM = ProxyTypeFactory.make(5, "SYSTEM")  # Use system settings (default on Linux).
        UNSPECIFIED = ProxyTypeFactory.make(6, "UNSPECIFIED")  # Not initialized (for internal use).

        @classmethod
        def load(cls, value):
            if isinstance(value, dict) and "string" in value:
                value = value["string"]
            value = str(value).upper()
            for attr in dir(cls):
                attr_value = getattr(cls, attr)
                if isinstance(attr_value, dict) and "string" in attr_value and attr_value["string"] == value:
                    return attr_value
            raise Exception(f"No proxy type is found for {value}")

    class _ProxyTypeDescriptor:
        def __init__(self, name, p_type):
            self.name = name
            self.p_type = p_type

        def __get__(self, obj, cls):
            return getattr(obj, self.name)

        def __set__(self, obj, value):
            if self.name == "autodetect" and not isinstance(value, bool):
                raise ValueError("Autodetect proxy value needs to be a boolean")
            getattr(obj, "_verify_proxy_type_compatibility")(self.p_type)
            setattr(obj, "proxyType", self.p_type)
            setattr(obj, self.name, value)

    class Proxy:
        """Proxy contains information about proxy type and necessary proxy
        settings."""

        proxyType = ProxyType.UNSPECIFIED
        autodetect = False
        ftpProxy = ""
        httpProxy = ""
        noProxy = ""
        proxyAutoconfigUrl = ""
        sslProxy = ""
        socksProxy = ""
        socksUsername = ""
        socksPassword = ""
        socksVersion = None

        # create descriptor type objects
        auto_detect = _ProxyTypeDescriptor("autodetect", ProxyType.AUTODETECT)
        """Gets and Sets `auto_detect`

        Usage
        -----
        - Get
            - `self.auto_detect`
        - Set
            - `self.auto_detect` = `value`

        Parameters
        ----------
        `value`: `str`
        """

        ftp_proxy = _ProxyTypeDescriptor("ftpProxy", ProxyType.MANUAL)
        """Gets and Sets `ftp_proxy`

        Usage
        -----
        - Get
            - `self.ftp_proxy`
        - Set
            - `self.ftp_proxy` = `value`

        Parameters
        ----------
        `value`: `str`
        """

        http_proxy = _ProxyTypeDescriptor("httpProxy", ProxyType.MANUAL)
        """Gets and Sets `http_proxy`

        Usage
        -----
        - Get
            - `self.http_proxy`
        - Set
            - `self.http_proxy` = `value`

        Parameters
        ----------
        `value`: `str`
        """

        no_proxy = _ProxyTypeDescriptor("noProxy", ProxyType.MANUAL)
        """Gets and Sets `no_proxy`

        Usage
        -----
        - Get
            - `self.no_proxy`
        - Set
            - `self.no_proxy` = `value`

        Parameters
        ----------
        `value`: `str`
        """

        proxy_autoconfig_url = _ProxyTypeDescriptor("proxyAutoconfigUrl", ProxyType.PAC)
        """Gets and Sets `proxy_autoconfig_url`

        Usage
        -----
        - Get
            - `self.proxy_autoconfig_url`
        - Set
            - `self.proxy_autoconfig_url` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        ssl_proxy = _ProxyTypeDescriptor("sslProxy", ProxyType.MANUAL)
        """Gets and Sets `ssl_proxy`

        Usage
        -----
        - Get
            - `self.ssl_proxy`
        - Set
            - `self.ssl_proxy` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        socks_proxy = _ProxyTypeDescriptor("socksProxy", ProxyType.MANUAL)
        """Gets and Sets `socks_proxy`

        Usage
        -----
        - Get
            - `self.sock_proxy`
        - Set
            - `self.socks_proxy` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        socks_username = _ProxyTypeDescriptor("socksUsername", ProxyType.MANUAL)
        """Gets and Sets `socks_password`

        Usage
        -----
        - Get
            - `self.socks_password`
        - Set
            - `self.socks_password` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        socks_password = _ProxyTypeDescriptor("socksPassword", ProxyType.MANUAL)
        """Gets and Sets `socks_password`

        Usage
        -----
        - Get
            - `self.socks_password`
        - Set
            - `self.socks_password` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        socks_version = _ProxyTypeDescriptor("socksVersion", ProxyType.MANUAL)
        """Gets and Sets `socks_version`

        Usage
        -----
        - Get
            - `self.socks_version`
        - Set
            - `self.socks_version` = `value`

        Parameter
        ---------
        `value`: `str`
        """

        def __init__(self, raw=None):
            """Creates a new Proxy.

            :Args:
             - raw: raw proxy data. If None, default class values are used.
            """
            if raw:
                if "proxyType" in raw and raw["proxyType"]:
                    self.proxy_type = ProxyType.load(raw["proxyType"])
                if "ftpProxy" in raw and raw["ftpProxy"]:
                    self.ftp_proxy = raw["ftpProxy"]
                if "httpProxy" in raw and raw["httpProxy"]:
                    self.http_proxy = raw["httpProxy"]
                if "noProxy" in raw and raw["noProxy"]:
                    self.no_proxy = raw["noProxy"]
                if "proxyAutoconfigUrl" in raw and raw["proxyAutoconfigUrl"]:
                    self.proxy_autoconfig_url = raw["proxyAutoconfigUrl"]
                if "sslProxy" in raw and raw["sslProxy"]:
                    self.sslProxy = raw["sslProxy"]
                if "autodetect" in raw and raw["autodetect"]:
                    self.auto_detect = raw["autodetect"]
                if "socksProxy" in raw and raw["socksProxy"]:
                    self.socks_proxy = raw["socksProxy"]
                if "socksUsername" in raw and raw["socksUsername"]:
                    self.socks_username = raw["socksUsername"]
                if "socksPassword" in raw and raw["socksPassword"]:
                    self.socks_password = raw["socksPassword"]
                if "socksVersion" in raw and raw["socksVersion"]:
                    self.socks_version = raw["socksVersion"]

        @property
        def proxy_type(self):
            """Returns proxy type as `ProxyType`."""
            return self.proxyType

        @proxy_type.setter
        def proxy_type(self, value) -> None:
            """Sets proxy type.

            :Args:
             - value: The proxy type.
            """
            self._verify_proxy_type_compatibility(value)
            self.proxyType = value

        def _verify_proxy_type_compatibility(self, compatible_proxy):
            if self.proxyType not in (ProxyType.UNSPECIFIED, compatible_proxy):
                raise ValueError(
                    f"Specified proxy type ({compatible_proxy}) not compatible with current setting ({self.proxyType})"
                )

        def to_capabilities(self):
            proxy_caps = {"proxyType": self.proxyType["string"].lower()}
            proxies = [
                "autodetect",
                "ftpProxy",
                "httpProxy",
                "proxyAutoconfigUrl",
                "sslProxy",
                "noProxy",
                "socksProxy",
                "socksUsername",
                "socksPassword",
                "socksVersion",
            ]
            for proxy in proxies:
                attr_value = getattr(self, proxy)
                if attr_value:
                    proxy_caps[proxy] = attr_value
            return proxy_caps