# pylint: disable=too-many-lines,too-many-statements
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
import datetime
from io import IOBase
from typing import Any, Callable, Dict, IO, Iterable, Optional, TypeVar, Union, overload
import urllib.parse

from azure.core.exceptions import (
    ClientAuthenticationError,
    HttpResponseError,
    ResourceExistsError,
    ResourceNotFoundError,
    ResourceNotModifiedError,
    map_error,
)
from azure.core.paging import ItemPaged
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import HttpResponse
from azure.core.rest import HttpRequest
from azure.core.tracing.decorator import distributed_trace
from azure.core.utils import case_insensitive_dict

from .. import models as _models
from .._serialization import Serializer
from .._vendor import _convert_request

T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]

_SERIALIZER = Serializer()
_SERIALIZER.client_side_validation = False


def build_list_chat_read_receipts_request(
    chat_thread_id: str, *, max_page_size: Optional[int] = None, skip: Optional[int] = None, **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/readReceipts")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    if max_page_size is not None:
        _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int")
    if skip is not None:
        _params["skip"] = _SERIALIZER.query("skip", skip, "int")
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)


def build_send_chat_read_receipt_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/readReceipts")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)


def build_send_chat_message_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/messages")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)


def build_list_chat_messages_request(
    chat_thread_id: str,
    *,
    max_page_size: Optional[int] = None,
    start_time: Optional[datetime.datetime] = None,
    **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/messages")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    if max_page_size is not None:
        _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int")
    if start_time is not None:
        _params["startTime"] = _SERIALIZER.query("start_time", start_time, "iso-8601")
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)


def build_get_chat_message_request(chat_thread_id: str, chat_message_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/messages/{chatMessageId}")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
        "chatMessageId": _SERIALIZER.url("chat_message_id", chat_message_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)


def build_update_chat_message_request(chat_thread_id: str, chat_message_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/messages/{chatMessageId}")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
        "chatMessageId": _SERIALIZER.url("chat_message_id", chat_message_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs)


def build_delete_chat_message_request(chat_thread_id: str, chat_message_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/messages/{chatMessageId}")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
        "chatMessageId": _SERIALIZER.url("chat_message_id", chat_message_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs)


def build_list_chat_participants_request(
    chat_thread_id: str, *, max_page_size: Optional[int] = None, skip: Optional[int] = None, **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/participants")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    if max_page_size is not None:
        _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int")
    if skip is not None:
        _params["skip"] = _SERIALIZER.query("skip", skip, "int")
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)


def build_remove_chat_participant_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/participants/:remove")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)


def build_add_chat_participants_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/participants/:add")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)


def build_update_chat_thread_properties_request(  # pylint: disable=name-too-long
    chat_thread_id: str, **kwargs: Any
) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs)


def build_get_chat_thread_properties_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs)


def build_send_typing_notification_request(chat_thread_id: str, **kwargs: Any) -> HttpRequest:
    _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
    _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

    api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2024-03-07"))
    content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
    accept = _headers.pop("Accept", "application/json")

    # Construct URL
    _url = kwargs.pop("template_url", "/chat/threads/{chatThreadId}/typing")
    path_format_arguments = {
        "chatThreadId": _SERIALIZER.url("chat_thread_id", chat_thread_id, "str"),
    }

    _url: str = _url.format(**path_format_arguments)  # type: ignore

    # Construct parameters
    _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str")

    # Construct headers
    if content_type is not None:
        _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str")
    _headers["Accept"] = _SERIALIZER.header("accept", accept, "str")

    return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs)


class ChatThreadOperations:
    """
    .. warning::
        **DO NOT** instantiate this class directly.

        Instead, you should access the following operations through
        :class:`~azure.communication.chat.AzureCommunicationChatService`'s
        :attr:`chat_thread` attribute.
    """

    models = _models

    def __init__(self, *args, **kwargs):
        input_args = list(args)
        self._client = input_args.pop(0) if input_args else kwargs.pop("client")
        self._config = input_args.pop(0) if input_args else kwargs.pop("config")
        self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
        self._deserialize = input_args.pop(0) if input_args else kwargs.pop("deserializer")

    @distributed_trace
    def list_chat_read_receipts(
        self, chat_thread_id: str, max_page_size: Optional[int] = None, skip: Optional[int] = None, **kwargs: Any
    ) -> Iterable["_models.ChatMessageReadReceipt"]:
        """Gets chat message read receipts for a thread.

        Gets chat message read receipts for a thread.

        :param chat_thread_id: Thread id to get the chat message read receipts for. Required.
        :type chat_thread_id: str
        :param max_page_size: The maximum number of chat message read receipts to be returned per page.
         Default value is None.
        :type max_page_size: int
        :param skip: Skips chat message read receipts up to a specified position in response. Default
         value is None.
        :type skip: int
        :return: An iterator like instance of either ChatMessageReadReceipt or the result of
         cls(response)
        :rtype: ~azure.core.paging.ItemPaged[~azure.communication.chat.models.ChatMessageReadReceipt]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.ChatMessageReadReceiptsCollection] = kwargs.pop("cls", None)

        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_chat_read_receipts_request(
                    chat_thread_id=chat_thread_id,
                    max_page_size=max_page_size,
                    skip=skip,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)
                _request.method = "GET"
            return _request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("ChatMessageReadReceiptsCollection", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
                raise HttpResponseError(response=response)

            return pipeline_response

        return ItemPaged(get_next, extract_data)

    @overload
    def send_chat_read_receipt(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_read_receipt_request: _models.SendReadReceiptRequest,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Sends a read receipt event to a thread, on behalf of a user.

        Sends a read receipt event to a thread, on behalf of a user.

        :param chat_thread_id: Thread id to send the read receipt event to. Required.
        :type chat_thread_id: str
        :param send_read_receipt_request: Read receipt details. Required.
        :type send_read_receipt_request: ~azure.communication.chat.models.SendReadReceiptRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def send_chat_read_receipt(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_read_receipt_request: IO[bytes],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Sends a read receipt event to a thread, on behalf of a user.

        Sends a read receipt event to a thread, on behalf of a user.

        :param chat_thread_id: Thread id to send the read receipt event to. Required.
        :type chat_thread_id: str
        :param send_read_receipt_request: Read receipt details. Required.
        :type send_read_receipt_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def send_chat_read_receipt(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_read_receipt_request: Union[_models.SendReadReceiptRequest, IO[bytes]],
        **kwargs: Any
    ) -> None:
        """Sends a read receipt event to a thread, on behalf of a user.

        Sends a read receipt event to a thread, on behalf of a user.

        :param chat_thread_id: Thread id to send the read receipt event to. Required.
        :type chat_thread_id: str
        :param send_read_receipt_request: Read receipt details. Is either a SendReadReceiptRequest type
         or a IO[bytes] type. Required.
        :type send_read_receipt_request: ~azure.communication.chat.models.SendReadReceiptRequest or
         IO[bytes]
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[None] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(send_read_receipt_request, (IOBase, bytes)):
            _content = send_read_receipt_request
        else:
            _json = self._serialize.body(send_read_receipt_request, "SendReadReceiptRequest")

        _request = build_send_chat_read_receipt_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore

    @overload
    def send_chat_message(
        self,
        chat_thread_id: str,
        send_chat_message_request: _models.SendChatMessageRequest,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SendChatMessageResult:
        """Sends a message to a thread.

        Sends a message to a thread.

        :param chat_thread_id: The thread id to send the message to. Required.
        :type chat_thread_id: str
        :param send_chat_message_request: Details of the message to send. Required.
        :type send_chat_message_request: ~azure.communication.chat.models.SendChatMessageRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: SendChatMessageResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.SendChatMessageResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def send_chat_message(
        self,
        chat_thread_id: str,
        send_chat_message_request: IO[bytes],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SendChatMessageResult:
        """Sends a message to a thread.

        Sends a message to a thread.

        :param chat_thread_id: The thread id to send the message to. Required.
        :type chat_thread_id: str
        :param send_chat_message_request: Details of the message to send. Required.
        :type send_chat_message_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: SendChatMessageResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.SendChatMessageResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def send_chat_message(
        self,
        chat_thread_id: str,
        send_chat_message_request: Union[_models.SendChatMessageRequest, IO[bytes]],
        **kwargs: Any
    ) -> _models.SendChatMessageResult:
        """Sends a message to a thread.

        Sends a message to a thread.

        :param chat_thread_id: The thread id to send the message to. Required.
        :type chat_thread_id: str
        :param send_chat_message_request: Details of the message to send. Is either a
         SendChatMessageRequest type or a IO[bytes] type. Required.
        :type send_chat_message_request: ~azure.communication.chat.models.SendChatMessageRequest or
         IO[bytes]
        :return: SendChatMessageResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.SendChatMessageResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.SendChatMessageResult] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(send_chat_message_request, (IOBase, bytes)):
            _content = send_chat_message_request
        else:
            _json = self._serialize.body(send_chat_message_request, "SendChatMessageRequest")

        _request = build_send_chat_message_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [201]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        deserialized = self._deserialize("SendChatMessageResult", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace
    def list_chat_messages(
        self,
        chat_thread_id: str,
        max_page_size: Optional[int] = None,
        start_time: Optional[datetime.datetime] = None,
        **kwargs: Any
    ) -> Iterable["_models.ChatMessage"]:
        """Gets a list of messages from a thread.

        Gets a list of messages from a thread.

        :param chat_thread_id: The thread id of the message. Required.
        :type chat_thread_id: str
        :param max_page_size: The maximum number of messages to be returned per page. Default value is
         None.
        :type max_page_size: int
        :param start_time: The earliest point in time to get messages up to. The timestamp should be in
         RFC3339 format: ``yyyy-MM-ddTHH:mm:ssZ``. Default value is None.
        :type start_time: ~datetime.datetime
        :return: An iterator like instance of either ChatMessage or the result of cls(response)
        :rtype: ~azure.core.paging.ItemPaged[~azure.communication.chat.models.ChatMessage]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.ChatMessagesCollection] = kwargs.pop("cls", None)

        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_chat_messages_request(
                    chat_thread_id=chat_thread_id,
                    max_page_size=max_page_size,
                    start_time=start_time,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)
                _request.method = "GET"
            return _request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("ChatMessagesCollection", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
                raise HttpResponseError(response=response)

            return pipeline_response

        return ItemPaged(get_next, extract_data)

    @distributed_trace
    def get_chat_message(self, chat_thread_id: str, chat_message_id: str, **kwargs: Any) -> _models.ChatMessage:
        """Gets a message by id.

        Gets a message by id.

        :param chat_thread_id: The thread id to which the message was sent. Required.
        :type chat_thread_id: str
        :param chat_message_id: The message id. Required.
        :type chat_message_id: str
        :return: ChatMessage or the result of cls(response)
        :rtype: ~azure.communication.chat.models.ChatMessage
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.ChatMessage] = kwargs.pop("cls", None)

        _request = build_get_chat_message_request(
            chat_thread_id=chat_thread_id,
            chat_message_id=chat_message_id,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        deserialized = self._deserialize("ChatMessage", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @overload
    def update_chat_message(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        chat_message_id: str,
        update_chat_message_request: _models.UpdateChatMessageRequest,
        *,
        content_type: str = "application/merge-patch+json",
        **kwargs: Any
    ) -> None:
        """Updates a message.

        Updates a message.

        :param chat_thread_id: The thread id to which the message was sent. Required.
        :type chat_thread_id: str
        :param chat_message_id: The message id. Required.
        :type chat_message_id: str
        :param update_chat_message_request: Details of the request to update the message. Required.
        :type update_chat_message_request: ~azure.communication.chat.models.UpdateChatMessageRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/merge-patch+json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def update_chat_message(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        chat_message_id: str,
        update_chat_message_request: IO[bytes],
        *,
        content_type: str = "application/merge-patch+json",
        **kwargs: Any
    ) -> None:
        """Updates a message.

        Updates a message.

        :param chat_thread_id: The thread id to which the message was sent. Required.
        :type chat_thread_id: str
        :param chat_message_id: The message id. Required.
        :type chat_message_id: str
        :param update_chat_message_request: Details of the request to update the message. Required.
        :type update_chat_message_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/merge-patch+json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def update_chat_message(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        chat_message_id: str,
        update_chat_message_request: Union[_models.UpdateChatMessageRequest, IO[bytes]],
        **kwargs: Any
    ) -> None:
        """Updates a message.

        Updates a message.

        :param chat_thread_id: The thread id to which the message was sent. Required.
        :type chat_thread_id: str
        :param chat_message_id: The message id. Required.
        :type chat_message_id: str
        :param update_chat_message_request: Details of the request to update the message. Is either a
         UpdateChatMessageRequest type or a IO[bytes] type. Required.
        :type update_chat_message_request: ~azure.communication.chat.models.UpdateChatMessageRequest or
         IO[bytes]
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[None] = kwargs.pop("cls", None)

        content_type = content_type or "application/merge-patch+json"
        _json = None
        _content = None
        if isinstance(update_chat_message_request, (IOBase, bytes)):
            _content = update_chat_message_request
        else:
            _json = self._serialize.body(update_chat_message_request, "UpdateChatMessageRequest")

        _request = build_update_chat_message_request(
            chat_thread_id=chat_thread_id,
            chat_message_id=chat_message_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore

    @distributed_trace
    def delete_chat_message(  # pylint: disable=inconsistent-return-statements
        self, chat_thread_id: str, chat_message_id: str, **kwargs: Any
    ) -> None:
        """Deletes a message.

        Deletes a message.

        :param chat_thread_id: The thread id to which the message was sent. Required.
        :type chat_thread_id: str
        :param chat_message_id: The message id. Required.
        :type chat_message_id: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[None] = kwargs.pop("cls", None)

        _request = build_delete_chat_message_request(
            chat_thread_id=chat_thread_id,
            chat_message_id=chat_message_id,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore

    @distributed_trace
    def list_chat_participants(
        self, chat_thread_id: str, max_page_size: Optional[int] = None, skip: Optional[int] = None, **kwargs: Any
    ) -> Iterable["_models.ChatParticipant"]:
        """Gets the participants of a thread.

        Gets the participants of a thread.

        :param chat_thread_id: Thread id to get participants for. Required.
        :type chat_thread_id: str
        :param max_page_size: The maximum number of participants to be returned per page. Default value
         is None.
        :type max_page_size: int
        :param skip: Skips participants up to a specified position in response. Default value is None.
        :type skip: int
        :return: An iterator like instance of either ChatParticipant or the result of cls(response)
        :rtype: ~azure.core.paging.ItemPaged[~azure.communication.chat.models.ChatParticipant]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.ChatParticipantsCollection] = kwargs.pop("cls", None)

        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_chat_participants_request(
                    chat_thread_id=chat_thread_id,
                    max_page_size=max_page_size,
                    skip=skip,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request = _convert_request(_request)
                path_format_arguments = {
                    "endpoint": self._serialize.url(
                        "self._config.endpoint", self._config.endpoint, "str", skip_quote=True
                    ),
                }
                _request.url = self._client.format_url(_request.url, **path_format_arguments)
                _request.method = "GET"
            return _request

        def extract_data(pipeline_response):
            deserialized = self._deserialize("ChatParticipantsCollection", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, iter(list_of_elem)

        def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
                raise HttpResponseError(response=response)

            return pipeline_response

        return ItemPaged(get_next, extract_data)

    @overload
    def remove_chat_participant(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        participant_communication_identifier: _models.CommunicationIdentifierModel,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Remove a participant from a thread.

        Remove a participant from a thread.

        :param chat_thread_id: Thread id to remove the participant from. Required.
        :type chat_thread_id: str
        :param participant_communication_identifier: Id of the thread participant to remove from the
         thread. Required.
        :type participant_communication_identifier:
         ~azure.communication.chat.models.CommunicationIdentifierModel
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def remove_chat_participant(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        participant_communication_identifier: IO[bytes],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Remove a participant from a thread.

        Remove a participant from a thread.

        :param chat_thread_id: Thread id to remove the participant from. Required.
        :type chat_thread_id: str
        :param participant_communication_identifier: Id of the thread participant to remove from the
         thread. Required.
        :type participant_communication_identifier: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Known values are: 'application/json', 'application/merge-patch+json'. Default value is
         "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def remove_chat_participant(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        participant_communication_identifier: Union[_models.CommunicationIdentifierModel, IO[bytes]],
        **kwargs: Any
    ) -> None:
        """Remove a participant from a thread.

        Remove a participant from a thread.

        :param chat_thread_id: Thread id to remove the participant from. Required.
        :type chat_thread_id: str
        :param participant_communication_identifier: Id of the thread participant to remove from the
         thread. Is either a CommunicationIdentifierModel type or a IO[bytes] type. Required.
        :type participant_communication_identifier:
         ~azure.communication.chat.models.CommunicationIdentifierModel or IO[bytes]
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[None] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(participant_communication_identifier, (IOBase, bytes)):
            _content = participant_communication_identifier
        else:
            _json = self._serialize.body(participant_communication_identifier, "CommunicationIdentifierModel")

        _request = build_remove_chat_participant_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore

    @overload
    def add_chat_participants(
        self,
        chat_thread_id: str,
        add_chat_participants_request: _models.AddChatParticipantsRequest,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.AddChatParticipantsResult:
        """Adds thread participants to a thread. If participants already exist, no change occurs.

        Adds thread participants to a thread. If participants already exist, no change occurs.

        :param chat_thread_id: Id of the thread to add participants to. Required.
        :type chat_thread_id: str
        :param add_chat_participants_request: Thread participants to be added to the thread. Required.
        :type add_chat_participants_request:
         ~azure.communication.chat.models.AddChatParticipantsRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: AddChatParticipantsResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.AddChatParticipantsResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def add_chat_participants(
        self,
        chat_thread_id: str,
        add_chat_participants_request: IO[bytes],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.AddChatParticipantsResult:
        """Adds thread participants to a thread. If participants already exist, no change occurs.

        Adds thread participants to a thread. If participants already exist, no change occurs.

        :param chat_thread_id: Id of the thread to add participants to. Required.
        :type chat_thread_id: str
        :param add_chat_participants_request: Thread participants to be added to the thread. Required.
        :type add_chat_participants_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: AddChatParticipantsResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.AddChatParticipantsResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def add_chat_participants(
        self,
        chat_thread_id: str,
        add_chat_participants_request: Union[_models.AddChatParticipantsRequest, IO[bytes]],
        **kwargs: Any
    ) -> _models.AddChatParticipantsResult:
        """Adds thread participants to a thread. If participants already exist, no change occurs.

        Adds thread participants to a thread. If participants already exist, no change occurs.

        :param chat_thread_id: Id of the thread to add participants to. Required.
        :type chat_thread_id: str
        :param add_chat_participants_request: Thread participants to be added to the thread. Is either
         a AddChatParticipantsRequest type or a IO[bytes] type. Required.
        :type add_chat_participants_request:
         ~azure.communication.chat.models.AddChatParticipantsRequest or IO[bytes]
        :return: AddChatParticipantsResult or the result of cls(response)
        :rtype: ~azure.communication.chat.models.AddChatParticipantsResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.AddChatParticipantsResult] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(add_chat_participants_request, (IOBase, bytes)):
            _content = add_chat_participants_request
        else:
            _json = self._serialize.body(add_chat_participants_request, "AddChatParticipantsRequest")

        _request = build_add_chat_participants_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [201]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        deserialized = self._deserialize("AddChatParticipantsResult", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @overload
    def update_chat_thread_properties(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        update_chat_thread_request: _models.UpdateChatThreadRequest,
        *,
        content_type: str = "application/merge-patch+json",
        **kwargs: Any
    ) -> None:
        """Updates a thread's properties.

        Updates a thread's properties.

        :param chat_thread_id: The id of the thread to update. Required.
        :type chat_thread_id: str
        :param update_chat_thread_request: Request payload for updating a chat thread. Required.
        :type update_chat_thread_request: ~azure.communication.chat.models.UpdateChatThreadRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/merge-patch+json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def update_chat_thread_properties(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        update_chat_thread_request: IO[bytes],
        *,
        content_type: str = "application/merge-patch+json",
        **kwargs: Any
    ) -> None:
        """Updates a thread's properties.

        Updates a thread's properties.

        :param chat_thread_id: The id of the thread to update. Required.
        :type chat_thread_id: str
        :param update_chat_thread_request: Request payload for updating a chat thread. Required.
        :type update_chat_thread_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/merge-patch+json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def update_chat_thread_properties(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        update_chat_thread_request: Union[_models.UpdateChatThreadRequest, IO[bytes]],
        **kwargs: Any
    ) -> None:
        """Updates a thread's properties.

        Updates a thread's properties.

        :param chat_thread_id: The id of the thread to update. Required.
        :type chat_thread_id: str
        :param update_chat_thread_request: Request payload for updating a chat thread. Is either a
         UpdateChatThreadRequest type or a IO[bytes] type. Required.
        :type update_chat_thread_request: ~azure.communication.chat.models.UpdateChatThreadRequest or
         IO[bytes]
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[None] = kwargs.pop("cls", None)

        content_type = content_type or "application/merge-patch+json"
        _json = None
        _content = None
        if isinstance(update_chat_thread_request, (IOBase, bytes)):
            _content = update_chat_thread_request
        else:
            _json = self._serialize.body(update_chat_thread_request, "UpdateChatThreadRequest")

        _request = build_update_chat_thread_properties_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [204]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore

    @distributed_trace
    def get_chat_thread_properties(self, chat_thread_id: str, **kwargs: Any) -> _models.ChatThreadProperties:
        """Gets a chat thread's properties.

        Gets a chat thread's properties.

        :param chat_thread_id: Id of the thread. Required.
        :type chat_thread_id: str
        :return: ChatThreadProperties or the result of cls(response)
        :rtype: ~azure.communication.chat.models.ChatThreadProperties
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.ChatThreadProperties] = kwargs.pop("cls", None)

        _request = build_get_chat_thread_properties_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        deserialized = self._deserialize("ChatThreadProperties", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @overload
    def send_typing_notification(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_typing_notification_request: Optional[_models.SendTypingNotificationRequest] = None,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Posts a typing event to a thread, on behalf of a user.

        Posts a typing event to a thread, on behalf of a user.

        :param chat_thread_id: Id of the thread. Required.
        :type chat_thread_id: str
        :param send_typing_notification_request: Details of the typing notification request. Default
         value is None.
        :type send_typing_notification_request:
         ~azure.communication.chat.models.SendTypingNotificationRequest
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    def send_typing_notification(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_typing_notification_request: Optional[IO[bytes]] = None,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> None:
        """Posts a typing event to a thread, on behalf of a user.

        Posts a typing event to a thread, on behalf of a user.

        :param chat_thread_id: Id of the thread. Required.
        :type chat_thread_id: str
        :param send_typing_notification_request: Details of the typing notification request. Default
         value is None.
        :type send_typing_notification_request: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace
    def send_typing_notification(  # pylint: disable=inconsistent-return-statements
        self,
        chat_thread_id: str,
        send_typing_notification_request: Optional[Union[_models.SendTypingNotificationRequest, IO[bytes]]] = None,
        **kwargs: Any
    ) -> None:
        """Posts a typing event to a thread, on behalf of a user.

        Posts a typing event to a thread, on behalf of a user.

        :param chat_thread_id: Id of the thread. Required.
        :type chat_thread_id: str
        :param send_typing_notification_request: Details of the typing notification request. Is either
         a SendTypingNotificationRequest type or a IO[bytes] type. Default value is None.
        :type send_typing_notification_request:
         ~azure.communication.chat.models.SendTypingNotificationRequest or IO[bytes]
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
            401: lambda response: ClientAuthenticationError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            403: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            429: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
            503: lambda response: HttpResponseError(
                response=response, model=self._deserialize(_models.CommunicationErrorResponse, response)
            ),
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[None] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(send_typing_notification_request, (IOBase, bytes)):
            _content = send_typing_notification_request
        else:
            if send_typing_notification_request is not None:
                _json = self._serialize.body(send_typing_notification_request, "SendTypingNotificationRequest")
            else:
                _json = None

        _request = build_send_typing_notification_request(
            chat_thread_id=chat_thread_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request = _convert_request(_request)
        path_format_arguments = {
            "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True),
        }
        _request.url = self._client.format_url(_request.url, **path_format_arguments)

        _stream = False
        pipeline_response: PipelineResponse = self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)  # type: ignore
            raise HttpResponseError(response=response)

        if cls:
            return cls(pipeline_response, None, {})  # type: ignore
