# coding: utf-8

"""
    Teambition Open API

    Teambition Open API

    The version of the OpenAPI document: 1.0.0
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


import copy
import http.client as httplib
import logging
from logging import FileHandler
import multiprocessing
import sys
import re
from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union
from typing_extensions import NotRequired, Self

import urllib3


JSON_SCHEMA_VALIDATION_KEYWORDS = {
    'multipleOf', 'maximum', 'exclusiveMaximum',
    'minimum', 'exclusiveMinimum', 'maxLength',
    'minLength', 'pattern', 'maxItems', 'minItems'
}

ServerVariablesT = Dict[str, str]

# 简化AuthSettings，统一使用snake_case命名
AuthSettings = TypedDict(
    "AuthSettings",
    {
        "app_id": str,
        "app_secret": str,
    }
)

class HostSettingVariable(TypedDict):
    description: str
    default_value: str
    enum_values: List[str]

class HostSetting(TypedDict):
    url: str
    description: str
    variables: NotRequired[Dict[str, HostSettingVariable]]

class Configuration:

    def __init__(
        self,
        app_id: str,
        app_secret: str,
        host: str = "https://open.teambition.com/api",
        ignore_operation_servers: bool = False,
        server_index: Optional[int] = None,
        server_variables: Optional[ServerVariablesT] = None,
        server_operation_index: Optional[Dict[str, int]] = None,
        server_operation_variables: Optional[Dict[str, ServerVariablesT]] = None,
        ssl_ca_cert: Optional[str] = None,
        retries: Optional[int] = None,
        ca_cert_data: Optional[Union[str, bytes]] = None,
    ) -> None:
        """Constructor
        """
        self.app_id = app_id
        self.app_secret = app_secret
        self.host = host
        self.ignore_operation_servers = ignore_operation_servers
        self.temp_folder_path = None
        # 移除无关鉴权配置
        self.server_index = server_index
        self.server_variables = server_variables
        self.server_operation_index = server_operation_index
        self.server_operation_variables = server_operation_variables
        self.client_side_validation = True
        self.socket_options = None
        if ca_cert_data:
            self.ssl_ca_cert_data = ca_cert_data
        else:
            self.ssl_ca_cert = ssl_ca_cert
        self.connection_pool_maxsize = multiprocessing.cpu_count() * 5
        self.retries = retries
        # Enable client side validation
        self.client_side_validation = True

        # The user agent string
        self.user_agent = 'OpenAPI-Generator/0.0.1-beta.0/python'

        # Logging Settings
        self.logger = {}
        self.logger["package_logger"] = logging.getLogger("teambition_oapi_sdk")
        self.logger["urllib3_logger"] = logging.getLogger("urllib3")
        self.logger_format = '%(asctime)s %(levelname)s %(message)s'
        self.logger_stream_handler = None
        self.logger_file_handler = None
        self.logger_file = None
        self.debug = False

    def __deepcopy__(self, memo):
        cls = self.__class__
        result = cls.__new__(cls)
        memo[id(self)] = result
        for k, v in self.__dict__.items():
            if k not in ('logger', 'logger_file_handler'):
                setattr(result, k, copy.deepcopy(v, memo))
        # shallow copy of loggers
        result.logger = copy.copy(self.logger)
        # use setters to configure loggers
        result.logger_file = self.logger_file
        result.debug = self.debug
        return result

    @property
    def logger_file(self):
        """The logger file.

        If the logger_file is None, then add stream handler and remove file
        handler. Otherwise, add file handler and remove stream handler.

        :param value: The logger_file path.
        :type: str
        """
        return self.__logger_file

    @logger_file.setter
    def logger_file(self, value):
        """The logger file.

        If the logger_file is None, then add stream handler and remove file
        handler. Otherwise, add file handler and remove stream handler.

        :param value: The logger_file path.
        :type: str
        """
        self.__logger_file = value
        if self.__logger_file:
            # If set logging file,
            # then add file handler and remove stream handler.
            self.logger_file_handler = FileHandler(self.__logger_file)
            self.logger_file_handler.setFormatter(self.logger_formatter)
            for _, logger in self.logger.items():
                logger.addHandler(self.logger_file_handler)

    @property
    def debug(self):
        """Debug status

        :param value: The debug status, True or False.
        :type: bool
        """
        return self.__debug

    @debug.setter
    def debug(self, value):
        """Debug status

        :param value: The debug status, True or False.
        :type: bool
        """
        self.__debug = value
        if self.__debug:
            # if debug status is True, turn on debug logging
            for _, logger in self.logger.items():
                logger.setLevel(logging.DEBUG)
            # turn on httplib debug
            httplib.HTTPConnection.debuglevel = 1
        else:
            # if debug status is False, turn off debug logging,
            # setting log level to default `logging.WARNING`
            for _, logger in self.logger.items():
                logger.setLevel(logging.WARNING)
            # turn off httplib debug
            httplib.HTTPConnection.debuglevel = 0

    @property
    def logger_format(self):
        """The logger format.

        The logger_formatter will be updated when sets logger_format.

        :param value: The format string.
        :type: str
        """
        return self.__logger_format

    @logger_format.setter
    def logger_format(self, value):
        """The logger format.

        The logger_formatter will be updated when sets logger_format.

        :param value: The format string.
        :type: str
        """
        self.__logger_format = value
        self.logger_formatter = logging.Formatter(self.__logger_format)

    # 简化鉴权设置，统一使用snake_case命名
    def auth_settings(self) -> AuthSettings:
        """Gets Auth Settings dict for api client.

        :return: The Auth Settings information dict.
        """
        return {
            "app_id": self.app_id,
            "app_secret": self.app_secret
        }

    def get_host_settings(self) -> List[HostSetting]:
        """Gets an array of host settings

        :return: An array of host settings
        """
        return [
            {
                'url': "https://open.teambition.com/api",
                'description': "No description provided",
            }
        ]

    def get_host_from_settings(self, index, variables: Optional[ServerVariablesT] = None, servers=None) -> str:
        """Gets host URL based on the index and variables
        :param index: array index of the host settings
        :param variables: hash of variable and the corresponding value
        :param servers: an array of host settings or None
        :return: URL based on host settings
        """
        if index is None:
            return self._base_path

        variables = {} if variables is None else variables
        servers = self.get_host_settings() if servers is None else servers

        try:
            server = servers[index]
        except IndexError:
            raise ValueError(
                "Invalid index {0} when selecting the host settings. "
                "Must be less than {1}".format(index, len(servers))
            )

        url = server['url']

        # go through variables and replace placeholders
        for variable_name, variable in server.get('variables', {}).items():
            used_value = variables.get(
                variable_name, variable['default_value'])

            if not re.match("^[A-Za-z0-9-._~!$&'()*+,;=:]+$", used_value):
                raise ValueError(
                    "The variable `{0}` in the host URL has an invalid value "
                    "{1}. Only alphanumeric characters and the "
                    "characters : . - _ ~ ! $ & ' ( ) * + , ; = are allowed".format(
                        variable_name, used_value))

            url = url.replace("{" + variable_name + "}", used_value)

        return url

    def is_json_mime(self, mime: str) -> bool:
        """Check if the given MIME is a JSON MIME.

        JSON MIME examples:
          application/json
          application/json; charset=UTF8
          APPLICATION/JSON
          application/vnd.company+json
        :param mime: MIME (Multipurpose Internet Mail Extensions)
        :return: True if the given MIME is JSON, false otherwise.
        """
        json_mime_pattern = r'^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$'
        return mime is not None and (re.match(json_mime_pattern, mime, re.IGNORECASE) is not None or mime.lower() == 'application/json-patch+json')