# 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 loads
from sys import version_info
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, ConfigDict

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


from algoliasearch.composition.models.around_precision import AroundPrecision
from algoliasearch.composition.models.around_radius import AroundRadius
from algoliasearch.composition.models.external_injected_item import ExternalInjectedItem
from algoliasearch.composition.models.facet_filters import FacetFilters
from algoliasearch.composition.models.inside_bounding_box import InsideBoundingBox
from algoliasearch.composition.models.numeric_filters import NumericFilters
from algoliasearch.composition.models.optional_filters import OptionalFilters
from algoliasearch.composition.models.supported_language import SupportedLanguage

_ALIASES = {
    "analytics": "analytics",
    "analytics_tags": "analyticsTags",
    "around_lat_lng": "aroundLatLng",
    "around_lat_lng_via_ip": "aroundLatLngViaIP",
    "around_radius": "aroundRadius",
    "around_precision": "aroundPrecision",
    "click_analytics": "clickAnalytics",
    "enable_ab_test": "enableABTest",
    "enable_personalization": "enablePersonalization",
    "enable_re_ranking": "enableReRanking",
    "enable_rules": "enableRules",
    "facet_filters": "facetFilters",
    "facets": "facets",
    "filters": "filters",
    "get_ranking_info": "getRankingInfo",
    "hits_per_page": "hitsPerPage",
    "injected_items": "injectedItems",
    "inside_bounding_box": "insideBoundingBox",
    "inside_polygon": "insidePolygon",
    "minimum_around_radius": "minimumAroundRadius",
    "natural_languages": "naturalLanguages",
    "numeric_filters": "numericFilters",
    "optional_filters": "optionalFilters",
    "page": "page",
    "query": "query",
    "query_languages": "queryLanguages",
    "relevancy_strictness": "relevancyStrictness",
    "rule_contexts": "ruleContexts",
    "sort_by": "sortBy",
    "user_token": "userToken",
}


def _alias_generator(name: str) -> str:
    return _ALIASES.get(name, name)


class Params(BaseModel):
    """
    Params
    """

    analytics: Optional[bool] = None
    """ Whether this search will be included in Analytics. """
    analytics_tags: Optional[List[str]] = None
    """ Tags to apply to the query for [segmenting analytics data](https://www.algolia.com/doc/guides/search-analytics/guides/segments). """
    around_lat_lng: Optional[str] = None
    """ Coordinates for the center of a circle, expressed as a comma-separated string of latitude and longitude.  Only records included within a circle around this central location are included in the results. The radius of the circle is determined by the `aroundRadius` and `minimumAroundRadius` settings. This parameter is ignored if you also specify `insidePolygon` or `insideBoundingBox`.  """
    around_lat_lng_via_ip: Optional[bool] = None
    """ Whether to obtain the coordinates from the request's IP address. """
    around_radius: Optional[AroundRadius] = None
    around_precision: Optional[AroundPrecision] = None
    click_analytics: Optional[bool] = None
    """ Whether to include a `queryID` attribute in the response The query ID is a unique identifier for a search query and is required for tracking [click and conversion events](https://www.algolia.com/doc/guides/sending-events/getting-started).  """
    enable_ab_test: Optional[bool] = None
    """ Whether to enable index level A/B testing for this run request. If the composition mixes multiple indices, the A/B test is ignored.  """
    enable_personalization: Optional[bool] = None
    """ Whether to enable Personalization. """
    enable_re_ranking: Optional[bool] = None
    """ Whether this search will use [Dynamic Re-Ranking](https://www.algolia.com/doc/guides/algolia-ai/re-ranking) This setting only has an effect if you activated Dynamic Re-Ranking for this index in the Algolia dashboard.  """
    enable_rules: Optional[bool] = None
    """ Whether to enable composition rules. """
    facet_filters: Optional[FacetFilters] = None
    facets: Optional[List[str]] = None
    """ Facets for which to retrieve facet values that match the search criteria and the number of matching facet values To retrieve all facets, use the wildcard character `*`. To retrieve disjunctive facets lists, annotate any facets with the `disjunctive` modifier. For more information, see [facets](https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/#contextual-facet-values-and-counts) and [disjunctive faceting for Smart Groups](https://www.algolia.com/doc/guides/managing-results/compositions/search-based-groups#facets-including-disjunctive-faceting).  """
    filters: Optional[str] = None
    """ Filter expression to only include items that match the filter criteria in the response.  You can use these filter expressions:  - **Numeric filters.** `<facet> <op> <number>`, where `<op>` is one of `<`, `<=`, `=`, `!=`, `>`, `>=`. - **Ranges.** `<facet>:<lower> TO <upper>` where `<lower>` and `<upper>` are the lower and upper limits of the range (inclusive). - **Facet filters.** `<facet>:<value>` where `<facet>` is a facet attribute (case-sensitive) and `<value>` a facet value. - **Tag filters.** `_tags:<value>` or just `<value>` (case-sensitive). - **Boolean filters.** `<facet>: true | false`.  You can combine filters with `AND`, `OR`, and `NOT` operators with the following restrictions:  - You can only combine filters of the same type with `OR`.   **Not supported:** `facet:value OR num > 3`. - You can't use `NOT` with combinations of filters.   **Not supported:** `NOT(facet:value OR facet:value)` - You can't combine conjunctions (`AND`) with `OR`.   **Not supported:** `facet:value OR (facet:value AND facet:value)`  Use quotes around your filters, if the facet attribute name or facet value has spaces, keywords (`OR`, `AND`, `NOT`), or quotes. If a facet attribute is an array, the filter matches if it matches at least one element of the array.  For more information, see [Filters](https://www.algolia.com/doc/guides/managing-results/refine-results/filtering).  """
    get_ranking_info: Optional[bool] = None
    """ Whether the run response should include detailed ranking information. """
    hits_per_page: Optional[int] = None
    """ Number of hits per page. """
    injected_items: Optional[Dict[str, ExternalInjectedItem]] = None
    """ A list of extenrally injected objectID groups into from an external source.  """
    inside_bounding_box: Optional[InsideBoundingBox] = None
    inside_polygon: Optional[List[List[float]]] = None
    """ Coordinates of a polygon in which to search.  Polygons are defined by 3 to 10,000 points. Each point is represented by its latitude and longitude. Provide multiple polygons as nested arrays. For more information, see [filtering inside polygons](https://www.algolia.com/doc/guides/managing-results/refine-results/geolocation/#filtering-inside-rectangular-or-polygonal-areas). This parameter is ignored if you also specify `insideBoundingBox`.  """
    minimum_around_radius: Optional[int] = None
    """ Minimum radius (in meters) for a search around a location when `aroundRadius` isn't set. """
    natural_languages: Optional[List[SupportedLanguage]] = None
    """ ISO language codes that adjust settings that are useful for processing natural language queries (as opposed to keyword searches) - Sets `removeStopWords` and `ignorePlurals` to the list of provided languages. - Sets `removeWordsIfNoResults` to `allOptional`. - Adds a `natural_language` attribute to `ruleContexts` and `analyticsTags`.  """
    numeric_filters: Optional[NumericFilters] = None
    optional_filters: Optional[OptionalFilters] = None
    page: Optional[int] = None
    """ Page of search results to retrieve. """
    query: Optional[str] = None
    """ Search query. """
    query_languages: Optional[List[SupportedLanguage]] = None
    """ Languages for language-specific query processing steps such as plurals, stop-word removal, and word-detection dictionaries  This setting sets a default list of languages used by the `removeStopWords` and `ignorePlurals` settings. This setting also sets a dictionary for word detection in the logogram-based [CJK](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/in-depth/normalization/#normalization-for-logogram-based-languages-cjk) languages. To support this, you must place the CJK language **first**  **You should always specify a query language.** If you don't specify an indexing language, the search engine uses all [supported languages](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/in-depth/supported-languages), or the languages you specified with the `ignorePlurals` or `removeStopWords` parameters. This can lead to unexpected search results. For more information, see [Language-specific configuration](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/handling-natural-languages-nlp/in-depth/language-specific-configurations).  """
    relevancy_strictness: Optional[int] = None
    """ Relevancy threshold below which less relevant results aren't included in the results You can only set `relevancyStrictness` on [virtual replica indices](https://www.algolia.com/doc/guides/managing-results/refine-results/sorting/in-depth/replicas/#what-are-virtual-replicas). Use this setting to strike a balance between the relevance and number of returned results.  """
    rule_contexts: Optional[List[str]] = None
    """ Assigns a rule context to the run query [Rule contexts](https://www.algolia.com/doc/guides/managing-results/rules/rules-overview/how-to/customize-search-results-by-platform/#whats-a-context) are strings that you can use to trigger matching rules.  """
    sort_by: Optional[str] = None
    """ Indicates which sorting strategy to apply for the request. The value must match one of the labels defined in the \"sortingStrategy\" mapping. For example, \"Price (asc)\", see Upsert Composition. At runtime, this label is used to look up the corresponding index or replica configured in \"sortingStrategy\", and the query is executed using that index instead of main's.  In addition to \"sortingStrategy\", this parameter is also used to apply a matching Composition Rule that contains a condition defined to trigger on \"sortBy\", see Composition Rules.  If no value is provided or an invalid value, no sorting strategy is applied.  """
    user_token: Optional[str] = None
    """ Unique pseudonymous or anonymous user identifier.  This helps with analytics and click and conversion events. For more information, see [user token](https://www.algolia.com/doc/guides/sending-events/concepts/usertoken).  """

    model_config = ConfigDict(
        strict=False,
        use_enum_values=True,
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
        alias_generator=_alias_generator,
        extra="allow",
    )

    def to_json(self) -> str:
        return self.model_dump_json(by_alias=True, exclude_unset=True)

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of Params from a JSON string"""
        return cls.from_dict(loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias."""
        return self.model_dump(
            by_alias=True,
            exclude_none=True,
            exclude_unset=True,
        )

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of Params from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        obj["aroundRadius"] = (
            AroundRadius.from_dict(obj["aroundRadius"])
            if obj.get("aroundRadius") is not None
            else None
        )
        obj["aroundPrecision"] = (
            AroundPrecision.from_dict(obj["aroundPrecision"])
            if obj.get("aroundPrecision") is not None
            else None
        )
        obj["facetFilters"] = (
            FacetFilters.from_dict(obj["facetFilters"])
            if obj.get("facetFilters") is not None
            else None
        )
        obj["injectedItems"] = (
            dict(
                (_k, ExternalInjectedItem.from_dict(_v))
                for _k, _v in obj["injectedItems"].items()
            )
            if obj.get("injectedItems") is not None
            else None
        )
        obj["insideBoundingBox"] = (
            InsideBoundingBox.from_dict(obj["insideBoundingBox"])
            if obj.get("insideBoundingBox") is not None
            else None
        )
        obj["naturalLanguages"] = obj.get("naturalLanguages")
        obj["numericFilters"] = (
            NumericFilters.from_dict(obj["numericFilters"])
            if obj.get("numericFilters") is not None
            else None
        )
        obj["optionalFilters"] = (
            OptionalFilters.from_dict(obj["optionalFilters"])
            if obj.get("optionalFilters") is not None
            else None
        )
        obj["queryLanguages"] = obj.get("queryLanguages")

        return cls.model_validate(obj)
