# coding: utf-8

"""
Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT.
"""

from __future__ import annotations

from json import dumps
from sys import version_info
from typing import Any, Dict, Optional, Union
from urllib.parse import quote

from pydantic import Field, StrictInt, StrictStr
from typing_extensions import Annotated

if version_info >= (3, 11):
    from typing import Self
else:
    from typing_extensions import Self

from algoliasearch.composition.config import CompositionConfig
from algoliasearch.composition.models import (
    BatchParams,
    Composition,
    CompositionRule,
    CompositionRulesBatchParams,
    GetTaskResponse,
    ListCompositionsResponse,
    MultipleBatchResponse,
    RequestBody,
    RulesMultipleBatchResponse,
    SearchCompositionRulesParams,
    SearchCompositionRulesResponse,
    SearchForFacetValuesRequest,
    SearchForFacetValuesResponse,
    SearchResponse,
    TaskIDResponse,
)
from algoliasearch.http.api_response import ApiResponse
from algoliasearch.http.base_config import BaseConfig
from algoliasearch.http.request_options import RequestOptions
from algoliasearch.http.serializer import body_serializer
from algoliasearch.http.transporter import Transporter
from algoliasearch.http.transporter_sync import TransporterSync
from algoliasearch.http.verb import Verb


class CompositionClient:
    """The Algolia 'CompositionClient' class.

    Args:
    app_id (str): The Algolia application ID to retrieve information from.
    api_key (str): The Algolia api key bound to the given `app_id`.


    Returns:
    The initialized API client.

    Example:
    _client = CompositionClient("YOUR_ALGOLIA_APP_ID", "YOUR_ALGOLIA_API_KEY")
    _client_with_named_args = CompositionClient(app_id="YOUR_ALGOLIA_APP_ID", api_key="YOUR_ALGOLIA_API_KEY")

    See `CompositionClient.create_with_config` for advanced configuration.
    """

    _transporter: Transporter
    _config: BaseConfig
    _request_options: RequestOptions

    def __init__(
        self,
        app_id: Optional[str] = None,
        api_key: Optional[str] = None,
        transporter: Optional[Transporter] = None,
        config: Optional[CompositionConfig] = None,
    ) -> None:
        if transporter is not None and config is None:
            config = CompositionConfig(
                transporter.config.app_id, transporter.config.api_key
            )
        elif config is None:
            config = CompositionConfig(app_id, api_key)

        config.set_default_hosts()

        self._config = config
        self._request_options = RequestOptions(config)

        if transporter is None:
            transporter = Transporter(config)
        self._transporter = transporter

    @classmethod
    def create_with_config(
        cls, config: CompositionConfig, transporter: Optional[Transporter] = None
    ) -> CompositionClient:
        """Allows creating a client with a customized `CompositionConfig` and `Transporter`. If `transporter` is not provided, the default one will be initialized from the given `config`.

        Args:
        config (CompositionConfig): The config of the API client.
        transporter (Transporter): The HTTP transporter, see `http/transporter.py` for implementation details.

        Returns:
        The initialized API client.

        Example:
        _client_with_custom_config = CompositionClient.create_with_config(config=CompositionConfig(...))
        _client_with_custom_config_and_transporter = CompositionClient.create_with_config(config=CompositionConfig(...), transporter=Transporter(...))
        """
        if transporter is None:
            transporter = Transporter(config)

        client = CompositionClient(
            app_id=config.app_id,
            api_key=config.api_key,
            transporter=transporter,
            config=config,
        )

        return client

    async def __aenter__(self) -> Self:
        return self

    async def __aexit__(self, exc_type, exc_value, traceback) -> None:
        """Closes the underlying `transporter` of the API client."""
        await self.close()

    async def close(self) -> None:
        """Closes the underlying `transporter` of the API client."""
        return await self._transporter.close()

    async def set_client_api_key(self, api_key: str) -> None:
        """Sets a new API key to authenticate requests."""
        self._transporter.config.set_client_api_key(api_key)

    async def add_user_agent(self, segment: str, version: Optional[str] = None) -> None:
        """adds a segment to the default user agent, and update the headers sent with each requests as well"""
        self._transporter.config.add_user_agent(segment, version)

    async def custom_delete_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError(
                "Parameter `path` is required when calling `custom_delete`."
            )

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        return await self._transporter.request(
            verb=Verb.DELETE,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def custom_delete(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = await self.custom_delete_with_http_info(
            path, parameters, request_options
        )
        return resp.deserialize(object, resp.raw_data)

    async def custom_get_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_get`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        return await self._transporter.request(
            verb=Verb.GET,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def custom_get(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = await self.custom_get_with_http_info(path, parameters, request_options)
        return resp.deserialize(object, resp.raw_data)

    async def custom_post_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_post`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        _data = {}
        if body is not None:
            _data = body

        return await self._transporter.request(
            verb=Verb.POST,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def custom_post(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = await self.custom_post_with_http_info(
            path, parameters, body, request_options
        )
        return resp.deserialize(object, resp.raw_data)

    async def custom_put_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_put`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        _data = {}
        if body is not None:
            _data = body

        return await self._transporter.request(
            verb=Verb.PUT,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def custom_put(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = await self.custom_put_with_http_info(
            path, parameters, body, request_options
        )
        return resp.deserialize(object, resp.raw_data)

    async def delete_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Delete a composition from the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `delete_composition`."
            )

        return await self._transporter.request(
            verb=Verb.DELETE,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def delete_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Delete a composition from the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = await self.delete_composition_with_http_info(
            composition_id, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    async def delete_composition_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Delete a Composition Rule from the specified Composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `delete_composition_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `delete_composition_rule`."
            )

        return await self._transporter.request(
            verb=Verb.DELETE,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def delete_composition_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Delete a Composition Rule from the specified Composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = await self.delete_composition_rule_with_http_info(
            composition_id, object_id, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    async def get_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Retrieve a single composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_composition`."
            )

        return await self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def get_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> Composition:
        """
        Retrieve a single composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'Composition' result object.
        """
        resp = await self.get_composition_with_http_info(
            composition_id, request_options
        )
        return resp.deserialize(Composition, resp.raw_data)

    async def get_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](#tag/Rules/operation/searchRules).

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `get_rule`."
            )

        return await self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def get_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> CompositionRule:
        """
        Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](#tag/Rules/operation/searchRules).

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'CompositionRule' result object.
        """
        resp = await self.get_rule_with_http_info(
            composition_id, object_id, request_options
        )
        return resp.deserialize(CompositionRule, resp.raw_data)

    async def get_task_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        task_id: Annotated[StrictInt, Field(description="Unique task identifier.")],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Checks the status of a given task.

        Required API Key ACLs:
          - editSettings
                  - settings
                  - addObject
                  - deleteObject
                  - deleteIndex

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param task_id: Unique task identifier. (required)
        :type task_id: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_task`."
            )

        if task_id is None:
            raise ValueError("Parameter `task_id` is required when calling `get_task`.")

        return await self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}/task/{taskID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{taskID}", quote(str(task_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def get_task(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        task_id: Annotated[StrictInt, Field(description="Unique task identifier.")],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> GetTaskResponse:
        """
        Checks the status of a given task.

        Required API Key ACLs:
          - editSettings
                  - settings
                  - addObject
                  - deleteObject
                  - deleteIndex

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param task_id: Unique task identifier. (required)
        :type task_id: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'GetTaskResponse' result object.
        """
        resp = await self.get_task_with_http_info(
            composition_id, task_id, request_options
        )
        return resp.deserialize(GetTaskResponse, resp.raw_data)

    async def list_compositions_with_http_info(
        self,
        page: Annotated[
            Optional[Annotated[int, Field(strict=True, ge=0)]],
            Field(
                description="Requested page of the API response. If `null`, the API response is not paginated. "
            ),
        ] = None,
        hits_per_page: Annotated[
            Optional[StrictInt], Field(description="Number of hits per page.")
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Lists all compositions in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param page: Requested page of the API response. If `null`, the API response is not paginated.
        :type page: int
        :param hits_per_page: Number of hits per page.
        :type hits_per_page: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        _query_parameters: Dict[str, Any] = {}

        if page is not None:
            _query_parameters["page"] = page
        if hits_per_page is not None:
            _query_parameters["hitsPerPage"] = hits_per_page

        return await self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions",
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def list_compositions(
        self,
        page: Annotated[
            Optional[Annotated[int, Field(strict=True, ge=0)]],
            Field(
                description="Requested page of the API response. If `null`, the API response is not paginated. "
            ),
        ] = None,
        hits_per_page: Annotated[
            Optional[StrictInt], Field(description="Number of hits per page.")
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ListCompositionsResponse:
        """
        Lists all compositions in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param page: Requested page of the API response. If `null`, the API response is not paginated.
        :type page: int
        :param hits_per_page: Number of hits per page.
        :type hits_per_page: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'ListCompositionsResponse' result object.
        """
        resp = await self.list_compositions_with_http_info(
            page, hits_per_page, request_options
        )
        return resp.deserialize(ListCompositionsResponse, resp.raw_data)

    async def multiple_batch_with_http_info(
        self,
        batch_params: Union[BatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Adds, updates, or deletes compositions with a single API request.

        Required API Key ACLs:
          - editSettings

        :param batch_params: (required)
        :type batch_params: BatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if batch_params is None:
            raise ValueError(
                "Parameter `batch_params` is required when calling `multiple_batch`."
            )

        _data = {}
        if batch_params is not None:
            _data = batch_params

        return await self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/*/batch",
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def multiple_batch(
        self,
        batch_params: Union[BatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> MultipleBatchResponse:
        """
        Adds, updates, or deletes compositions with a single API request.

        Required API Key ACLs:
          - editSettings

        :param batch_params: (required)
        :type batch_params: BatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'MultipleBatchResponse' result object.
        """
        resp = await self.multiple_batch_with_http_info(batch_params, request_options)
        return resp.deserialize(MultipleBatchResponse, resp.raw_data)

    async def put_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        composition: Union[Composition, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Upsert a composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param composition: (required)
        :type composition: Composition
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `put_composition`."
            )

        if composition is None:
            raise ValueError(
                "Parameter `composition` is required when calling `put_composition`."
            )

        _data = {}
        if composition is not None:
            _data = composition

        return await self._transporter.request(
            verb=Verb.PUT,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def put_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        composition: Union[Composition, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Upsert a composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param composition: (required)
        :type composition: Composition
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = await self.put_composition_with_http_info(
            composition_id, composition, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    async def put_composition_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        composition_rule: Union[CompositionRule, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Upsert a Composition Rule for the specified composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param composition_rule: (required)
        :type composition_rule: CompositionRule
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `put_composition_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `put_composition_rule`."
            )

        if composition_rule is None:
            raise ValueError(
                "Parameter `composition_rule` is required when calling `put_composition_rule`."
            )

        _data = {}
        if composition_rule is not None:
            _data = composition_rule

        return await self._transporter.request(
            verb=Verb.PUT,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def put_composition_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        composition_rule: Union[CompositionRule, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Upsert a Composition Rule for the specified composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param composition_rule: (required)
        :type composition_rule: CompositionRule
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = await self.put_composition_rule_with_http_info(
            composition_id, object_id, composition_rule, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    async def save_rules_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        rules: Union[CompositionRulesBatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Create or update or delete multiple composition rules.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param rules: (required)
        :type rules: CompositionRulesBatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `save_rules`."
            )

        if rules is None:
            raise ValueError("Parameter `rules` is required when calling `save_rules`.")

        _data = {}
        if rules is not None:
            _data = rules

        return await self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/rules/batch".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def save_rules(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        rules: Union[CompositionRulesBatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> RulesMultipleBatchResponse:
        """
        Create or update or delete multiple composition rules.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param rules: (required)
        :type rules: CompositionRulesBatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'RulesMultipleBatchResponse' result object.
        """
        resp = await self.save_rules_with_http_info(
            composition_id, rules, request_options
        )
        return resp.deserialize(RulesMultipleBatchResponse, resp.raw_data)

    async def search_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_body: Union[RequestBody, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Runs a query on a single composition and returns matching results.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_body: (required)
        :type request_body: RequestBody
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search`."
            )

        if request_body is None:
            raise ValueError(
                "Parameter `request_body` is required when calling `search`."
            )

        _data = {}
        if request_body is not None:
            _data = request_body

        return await self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/run".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=True,
        )

    async def search(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_body: Union[RequestBody, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchResponse:
        """
        Runs a query on a single composition and returns matching results.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_body: (required)
        :type request_body: RequestBody
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchResponse' result object.
        """
        resp = await self.search_with_http_info(
            composition_id, request_body, request_options
        )
        return resp.deserialize(SearchResponse, resp.raw_data)

    async def search_composition_rules_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        search_composition_rules_params: Union[
            Optional[SearchCompositionRulesParams], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Searches for composition rules in your index.

        Required API Key ACLs:
          - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param search_composition_rules_params:
        :type search_composition_rules_params: SearchCompositionRulesParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search_composition_rules`."
            )

        _data = {}
        if search_composition_rules_params is not None:
            _data = search_composition_rules_params

        return await self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/rules/search".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    async def search_composition_rules(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        search_composition_rules_params: Union[
            Optional[SearchCompositionRulesParams], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchCompositionRulesResponse:
        """
        Searches for composition rules in your index.

        Required API Key ACLs:
          - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param search_composition_rules_params:
        :type search_composition_rules_params: SearchCompositionRulesParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchCompositionRulesResponse' result object.
        """
        resp = await self.search_composition_rules_with_http_info(
            composition_id, search_composition_rules_params, request_options
        )
        return resp.deserialize(SearchCompositionRulesResponse, resp.raw_data)

    async def search_for_facet_values_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        facet_name: Annotated[
            StrictStr,
            Field(
                description="Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. "
            ),
        ],
        search_for_facet_values_request: Union[
            Optional[SearchForFacetValuesRequest], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Searches for values of a specified facet attribute on the composition's main source's index.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param facet_name: Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier.  (required)
        :type facet_name: str
        :param search_for_facet_values_request:
        :type search_for_facet_values_request: SearchForFacetValuesRequest
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search_for_facet_values`."
            )

        if facet_name is None:
            raise ValueError(
                "Parameter `facet_name` is required when calling `search_for_facet_values`."
            )

        _data = {}
        if search_for_facet_values_request is not None:
            _data = search_for_facet_values_request

        return await self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/facets/{facetName}/query".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{facetName}", quote(str(facet_name), safe="")),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=True,
        )

    async def search_for_facet_values(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        facet_name: Annotated[
            StrictStr,
            Field(
                description="Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. "
            ),
        ],
        search_for_facet_values_request: Union[
            Optional[SearchForFacetValuesRequest], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchForFacetValuesResponse:
        """
        Searches for values of a specified facet attribute on the composition's main source's index.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param facet_name: Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier.  (required)
        :type facet_name: str
        :param search_for_facet_values_request:
        :type search_for_facet_values_request: SearchForFacetValuesRequest
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchForFacetValuesResponse' result object.
        """
        resp = await self.search_for_facet_values_with_http_info(
            composition_id, facet_name, search_for_facet_values_request, request_options
        )
        return resp.deserialize(SearchForFacetValuesResponse, resp.raw_data)


class CompositionClientSync:
    """The Algolia 'CompositionClientSync' class.

    Args:
    app_id (str): The Algolia application ID to retrieve information from.
    api_key (str): The Algolia api key bound to the given `app_id`.


    Returns:
    The initialized API client.

    Example:
    _client = CompositionClientSync("YOUR_ALGOLIA_APP_ID", "YOUR_ALGOLIA_API_KEY")
    _client_with_named_args = CompositionClientSync(app_id="YOUR_ALGOLIA_APP_ID", api_key="YOUR_ALGOLIA_API_KEY")

    See `CompositionClientSync.create_with_config` for advanced configuration.
    """

    _transporter: TransporterSync
    _config: BaseConfig
    _request_options: RequestOptions

    def __init__(
        self,
        app_id: Optional[str] = None,
        api_key: Optional[str] = None,
        transporter: Optional[TransporterSync] = None,
        config: Optional[CompositionConfig] = None,
    ) -> None:
        if transporter is not None and config is None:
            config = CompositionConfig(
                transporter.config.app_id, transporter.config.api_key
            )
        elif config is None:
            config = CompositionConfig(app_id, api_key)

        config.set_default_hosts()

        self._config = config
        self._request_options = RequestOptions(config)

        if transporter is None:
            transporter = TransporterSync(config)
        self._transporter = transporter

    @classmethod
    def create_with_config(
        cls, config: CompositionConfig, transporter: Optional[TransporterSync] = None
    ) -> CompositionClientSync:
        """Allows creating a client with a customized `CompositionConfig` and `TransporterSync`. If `transporter` is not provided, the default one will be initialized from the given `config`.

        Args:
        config (CompositionConfig): The config of the API client.
        transporter (TransporterSync): The HTTP transporter, see `http/transporter.py` for implementation details.

        Returns:
        The initialized API client.

        Example:
        _client_with_custom_config = CompositionClientSync.create_with_config(config=CompositionConfig(...))
        _client_with_custom_config_and_transporter = CompositionClientSync.create_with_config(config=CompositionConfig(...), transporter=TransporterSync(...))
        """
        if transporter is None:
            transporter = TransporterSync(config)

        client = CompositionClientSync(
            app_id=config.app_id,
            api_key=config.api_key,
            transporter=transporter,
            config=config,
        )

        return client

    def __enter__(self) -> Self:
        return self

    def __exit__(self, exc_type, exc_value, traceback) -> None:
        """Closes the underlying `transporter` of the API client."""
        self.close()

    def close(self) -> None:
        return self._transporter.close()

    def set_client_api_key(self, api_key: str) -> None:
        """Sets a new API key to authenticate requests."""
        self._transporter.config.set_client_api_key(api_key)

    def add_user_agent(self, segment: str, version: Optional[str] = None) -> None:
        """adds a segment to the default user agent, and update the headers sent with each requests as well"""
        self._transporter.config.add_user_agent(segment, version)

    def custom_delete_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError(
                "Parameter `path` is required when calling `custom_delete`."
            )

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        return self._transporter.request(
            verb=Verb.DELETE,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def custom_delete(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = self.custom_delete_with_http_info(path, parameters, request_options)
        return resp.deserialize(object, resp.raw_data)

    def custom_get_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_get`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        return self._transporter.request(
            verb=Verb.GET,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def custom_get(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = self.custom_get_with_http_info(path, parameters, request_options)
        return resp.deserialize(object, resp.raw_data)

    def custom_post_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_post`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        _data = {}
        if body is not None:
            _data = body

        return self._transporter.request(
            verb=Verb.POST,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def custom_post(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = self.custom_post_with_http_info(path, parameters, body, request_options)
        return resp.deserialize(object, resp.raw_data)

    def custom_put_with_http_info(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if path is None:
            raise ValueError("Parameter `path` is required when calling `custom_put`.")

        _query_parameters: Dict[str, Any] = {}

        if parameters is not None:
            for _qpkey, _qpvalue in parameters.items():
                _query_parameters[_qpkey] = _qpvalue

        _data = {}
        if body is not None:
            _data = body

        return self._transporter.request(
            verb=Verb.PUT,
            path="/{path}".replace("{path}", path),
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def custom_put(
        self,
        path: Annotated[
            StrictStr,
            Field(description="Path of the endpoint, for example `1/newFeature`."),
        ],
        parameters: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Query parameters to apply to the current query."),
        ] = None,
        body: Annotated[
            Optional[Dict[str, Any]],
            Field(description="Parameters to send with the custom request."),
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> object:
        """
        This method lets you send requests to the Algolia REST API.


        :param path: Path of the endpoint, for example `1/newFeature`. (required)
        :type path: str
        :param parameters: Query parameters to apply to the current query.
        :type parameters: Dict[str, object]
        :param body: Parameters to send with the custom request.
        :type body: object
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'object' result object.
        """
        resp = self.custom_put_with_http_info(path, parameters, body, request_options)
        return resp.deserialize(object, resp.raw_data)

    def delete_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Delete a composition from the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `delete_composition`."
            )

        return self._transporter.request(
            verb=Verb.DELETE,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def delete_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Delete a composition from the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = self.delete_composition_with_http_info(composition_id, request_options)
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    def delete_composition_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Delete a Composition Rule from the specified Composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `delete_composition_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `delete_composition_rule`."
            )

        return self._transporter.request(
            verb=Verb.DELETE,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def delete_composition_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Delete a Composition Rule from the specified Composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = self.delete_composition_rule_with_http_info(
            composition_id, object_id, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    def get_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Retrieve a single composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_composition`."
            )

        return self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def get_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> Composition:
        """
        Retrieve a single composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'Composition' result object.
        """
        resp = self.get_composition_with_http_info(composition_id, request_options)
        return resp.deserialize(Composition, resp.raw_data)

    def get_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](#tag/Rules/operation/searchRules).

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `get_rule`."
            )

        return self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def get_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> CompositionRule:
        """
        Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](#tag/Rules/operation/searchRules).

        Required API Key ACLs:
          - editSettings
                  - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'CompositionRule' result object.
        """
        resp = self.get_rule_with_http_info(composition_id, object_id, request_options)
        return resp.deserialize(CompositionRule, resp.raw_data)

    def get_task_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        task_id: Annotated[StrictInt, Field(description="Unique task identifier.")],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Checks the status of a given task.

        Required API Key ACLs:
          - editSettings
                  - settings
                  - addObject
                  - deleteObject
                  - deleteIndex

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param task_id: Unique task identifier. (required)
        :type task_id: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `get_task`."
            )

        if task_id is None:
            raise ValueError("Parameter `task_id` is required when calling `get_task`.")

        return self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions/{compositionID}/task/{taskID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{taskID}", quote(str(task_id), safe="")),
            request_options=self._request_options.merge(
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def get_task(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        task_id: Annotated[StrictInt, Field(description="Unique task identifier.")],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> GetTaskResponse:
        """
        Checks the status of a given task.

        Required API Key ACLs:
          - editSettings
                  - settings
                  - addObject
                  - deleteObject
                  - deleteIndex

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param task_id: Unique task identifier. (required)
        :type task_id: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'GetTaskResponse' result object.
        """
        resp = self.get_task_with_http_info(composition_id, task_id, request_options)
        return resp.deserialize(GetTaskResponse, resp.raw_data)

    def list_compositions_with_http_info(
        self,
        page: Annotated[
            Optional[Annotated[int, Field(strict=True, ge=0)]],
            Field(
                description="Requested page of the API response. If `null`, the API response is not paginated. "
            ),
        ] = None,
        hits_per_page: Annotated[
            Optional[StrictInt], Field(description="Number of hits per page.")
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Lists all compositions in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param page: Requested page of the API response. If `null`, the API response is not paginated.
        :type page: int
        :param hits_per_page: Number of hits per page.
        :type hits_per_page: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        _query_parameters: Dict[str, Any] = {}

        if page is not None:
            _query_parameters["page"] = page
        if hits_per_page is not None:
            _query_parameters["hitsPerPage"] = hits_per_page

        return self._transporter.request(
            verb=Verb.GET,
            path="/1/compositions",
            request_options=self._request_options.merge(
                query_parameters=_query_parameters,
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def list_compositions(
        self,
        page: Annotated[
            Optional[Annotated[int, Field(strict=True, ge=0)]],
            Field(
                description="Requested page of the API response. If `null`, the API response is not paginated. "
            ),
        ] = None,
        hits_per_page: Annotated[
            Optional[StrictInt], Field(description="Number of hits per page.")
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ListCompositionsResponse:
        """
        Lists all compositions in the current Algolia application.

        Required API Key ACLs:
          - editSettings
                  - settings

        :param page: Requested page of the API response. If `null`, the API response is not paginated.
        :type page: int
        :param hits_per_page: Number of hits per page.
        :type hits_per_page: int
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'ListCompositionsResponse' result object.
        """
        resp = self.list_compositions_with_http_info(
            page, hits_per_page, request_options
        )
        return resp.deserialize(ListCompositionsResponse, resp.raw_data)

    def multiple_batch_with_http_info(
        self,
        batch_params: Union[BatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Adds, updates, or deletes compositions with a single API request.

        Required API Key ACLs:
          - editSettings

        :param batch_params: (required)
        :type batch_params: BatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if batch_params is None:
            raise ValueError(
                "Parameter `batch_params` is required when calling `multiple_batch`."
            )

        _data = {}
        if batch_params is not None:
            _data = batch_params

        return self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/*/batch",
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def multiple_batch(
        self,
        batch_params: Union[BatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> MultipleBatchResponse:
        """
        Adds, updates, or deletes compositions with a single API request.

        Required API Key ACLs:
          - editSettings

        :param batch_params: (required)
        :type batch_params: BatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'MultipleBatchResponse' result object.
        """
        resp = self.multiple_batch_with_http_info(batch_params, request_options)
        return resp.deserialize(MultipleBatchResponse, resp.raw_data)

    def put_composition_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        composition: Union[Composition, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Upsert a composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param composition: (required)
        :type composition: Composition
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `put_composition`."
            )

        if composition is None:
            raise ValueError(
                "Parameter `composition` is required when calling `put_composition`."
            )

        _data = {}
        if composition is not None:
            _data = composition

        return self._transporter.request(
            verb=Verb.PUT,
            path="/1/compositions/{compositionID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def put_composition(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        composition: Union[Composition, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Upsert a composition in the current Algolia application.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param composition: (required)
        :type composition: Composition
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = self.put_composition_with_http_info(
            composition_id, composition, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    def put_composition_rule_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        composition_rule: Union[CompositionRule, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Upsert a Composition Rule for the specified composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param composition_rule: (required)
        :type composition_rule: CompositionRule
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `put_composition_rule`."
            )

        if object_id is None:
            raise ValueError(
                "Parameter `object_id` is required when calling `put_composition_rule`."
            )

        if composition_rule is None:
            raise ValueError(
                "Parameter `composition_rule` is required when calling `put_composition_rule`."
            )

        _data = {}
        if composition_rule is not None:
            _data = composition_rule

        return self._transporter.request(
            verb=Verb.PUT,
            path="/1/compositions/{compositionID}/rules/{objectID}".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{objectID}", quote(str(object_id), safe="")),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def put_composition_rule(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        object_id: Annotated[
            StrictStr, Field(description="Unique identifier of a rule object.")
        ],
        composition_rule: Union[CompositionRule, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> TaskIDResponse:
        """
        Upsert a Composition Rule for the specified composition ID.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param object_id: Unique identifier of a rule object. (required)
        :type object_id: str
        :param composition_rule: (required)
        :type composition_rule: CompositionRule
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'TaskIDResponse' result object.
        """
        resp = self.put_composition_rule_with_http_info(
            composition_id, object_id, composition_rule, request_options
        )
        return resp.deserialize(TaskIDResponse, resp.raw_data)

    def save_rules_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        rules: Union[CompositionRulesBatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Create or update or delete multiple composition rules.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param rules: (required)
        :type rules: CompositionRulesBatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `save_rules`."
            )

        if rules is None:
            raise ValueError("Parameter `rules` is required when calling `save_rules`.")

        _data = {}
        if rules is not None:
            _data = rules

        return self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/rules/batch".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def save_rules(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        rules: Union[CompositionRulesBatchParams, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> RulesMultipleBatchResponse:
        """
        Create or update or delete multiple composition rules.

        Required API Key ACLs:
          - editSettings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param rules: (required)
        :type rules: CompositionRulesBatchParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'RulesMultipleBatchResponse' result object.
        """
        resp = self.save_rules_with_http_info(composition_id, rules, request_options)
        return resp.deserialize(RulesMultipleBatchResponse, resp.raw_data)

    def search_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_body: Union[RequestBody, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Runs a query on a single composition and returns matching results.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_body: (required)
        :type request_body: RequestBody
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search`."
            )

        if request_body is None:
            raise ValueError(
                "Parameter `request_body` is required when calling `search`."
            )

        _data = {}
        if request_body is not None:
            _data = request_body

        return self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/run".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=True,
        )

    def search(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        request_body: Union[RequestBody, dict[str, Any]],
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchResponse:
        """
        Runs a query on a single composition and returns matching results.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param request_body: (required)
        :type request_body: RequestBody
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchResponse' result object.
        """
        resp = self.search_with_http_info(composition_id, request_body, request_options)
        return resp.deserialize(SearchResponse, resp.raw_data)

    def search_composition_rules_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        search_composition_rules_params: Union[
            Optional[SearchCompositionRulesParams], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Searches for composition rules in your index.

        Required API Key ACLs:
          - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param search_composition_rules_params:
        :type search_composition_rules_params: SearchCompositionRulesParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search_composition_rules`."
            )

        _data = {}
        if search_composition_rules_params is not None:
            _data = search_composition_rules_params

        return self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/rules/search".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=False,
        )

    def search_composition_rules(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        search_composition_rules_params: Union[
            Optional[SearchCompositionRulesParams], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchCompositionRulesResponse:
        """
        Searches for composition rules in your index.

        Required API Key ACLs:
          - settings

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param search_composition_rules_params:
        :type search_composition_rules_params: SearchCompositionRulesParams
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchCompositionRulesResponse' result object.
        """
        resp = self.search_composition_rules_with_http_info(
            composition_id, search_composition_rules_params, request_options
        )
        return resp.deserialize(SearchCompositionRulesResponse, resp.raw_data)

    def search_for_facet_values_with_http_info(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        facet_name: Annotated[
            StrictStr,
            Field(
                description="Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. "
            ),
        ],
        search_for_facet_values_request: Union[
            Optional[SearchForFacetValuesRequest], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> ApiResponse[str]:
        """
        Searches for values of a specified facet attribute on the composition's main source's index.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param facet_name: Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier.  (required)
        :type facet_name: str
        :param search_for_facet_values_request:
        :type search_for_facet_values_request: SearchForFacetValuesRequest
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the raw algoliasearch 'APIResponse' object.
        """

        if composition_id is None:
            raise ValueError(
                "Parameter `composition_id` is required when calling `search_for_facet_values`."
            )

        if facet_name is None:
            raise ValueError(
                "Parameter `facet_name` is required when calling `search_for_facet_values`."
            )

        _data = {}
        if search_for_facet_values_request is not None:
            _data = search_for_facet_values_request

        return self._transporter.request(
            verb=Verb.POST,
            path="/1/compositions/{compositionID}/facets/{facetName}/query".replace(
                "{compositionID}", quote(str(composition_id), safe="")
            ).replace("{facetName}", quote(str(facet_name), safe="")),
            request_options=self._request_options.merge(
                data=dumps(body_serializer(_data)),
                user_request_options=request_options,
            ),
            use_read_transporter=True,
        )

    def search_for_facet_values(
        self,
        composition_id: Annotated[
            StrictStr, Field(description="Unique Composition ObjectID.")
        ],
        facet_name: Annotated[
            StrictStr,
            Field(
                description="Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. "
            ),
        ],
        search_for_facet_values_request: Union[
            Optional[SearchForFacetValuesRequest], dict[str, Any]
        ] = None,
        request_options: Optional[Union[dict, RequestOptions]] = None,
    ) -> SearchForFacetValuesResponse:
        """
        Searches for values of a specified facet attribute on the composition's main source's index.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.

        Required API Key ACLs:
          - search

        :param composition_id: Unique Composition ObjectID. (required)
        :type composition_id: str
        :param facet_name: Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier.  (required)
        :type facet_name: str
        :param search_for_facet_values_request:
        :type search_for_facet_values_request: SearchForFacetValuesRequest
        :param request_options: The request options to send along with the query, they will be merged with the transporter base parameters (headers, query params, timeouts, etc.). (optional)
        :return: Returns the deserialized response in a 'SearchForFacetValuesResponse' result object.
        """
        resp = self.search_for_facet_values_with_http_info(
            composition_id, facet_name, search_for_facet_values_request, request_options
        )
        return resp.deserialize(SearchForFacetValuesResponse, resp.raw_data)
