# coding: utf-8

"""
    Pinterest REST API

    Pinterest's REST API

    The version of the OpenAPI document: 5.23.0
    Contact: blah+oapicf@cliffano.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

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


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from pinterestsdk.models.targeting_spec_age_bucket import TargetingSpecAgeBucket
from pinterestsdk.models.targeting_spec_app_type import TargetingSpecAppType
from pinterestsdk.models.targeting_spec_gender import TargetingSpecGender
from pinterestsdk.models.targeting_spec_shopping_retargeting import TargetingSpecShoppingRetargeting
from typing import Optional, Set
from typing_extensions import Self

class TargetingSpec(BaseModel):
    """
    Ad group targeting specification defining the ad group target audience. For example, `{\"APPTYPE\":[\"iphone\"], \"GENDER\":[\"male\"], \"LOCALE\":[\"en-US\"], \"LOCATION\":[\"501\"], \"MINIMUM_AGE\":\"18\", \"MAXIMUM_AGE\":\"65+\"}`
    """ # noqa: E501
    age_bucket: Optional[List[TargetingSpecAgeBucket]] = Field(default=None, description="**Legacy field.** Predefined age ranges. We recommend using MINIMUM_AGE and MAXIMUM_AGE instead for more flexible targeting. Cannot be combined with MINIMUM_AGE/MAXIMUM_AGE. If neither AGE_BUCKET nor MINIMUM_AGE/MAXIMUM_AGE are specified, all ages will be targeted.", alias="AGE_BUCKET")
    apptype: Optional[List[TargetingSpecAppType]] = Field(default=None, description="Allowed devices. If the APPTYPE field is missing, the default behavior in terms of ad delivery is that **All devices/apptypes** will be targeted.", alias="APPTYPE")
    audience_exclude: Optional[List[Annotated[str, Field(strict=True)]]] = Field(default=None, description="Excluded customer list IDs. Used to drive new customer acquisition goals. For example: [\"2542620905475\"]. Audience lists need to have at least 100 people with Pinterest accounts in them. If the AUDIENCE_EXCLUDE field is missing, the default behavior in terms of ad delivery is that **No users will be excluded**.", alias="AUDIENCE_EXCLUDE")
    audience_include: Optional[List[Annotated[str, Field(strict=True)]]] = Field(default=None, description="Targeted customer list IDs. For example: [\"2542620905473\"]. Audience lists need to have at least 100 people with Pinterest accounts in them Audience lists need to have at least 100 people with Pinterest accounts in them. If the AUDIENCE_INCLUDE field is missing, the default behavior in terms of ad delivery is that **All users will be included**.", alias="AUDIENCE_INCLUDE")
    gender: Optional[List[TargetingSpecGender]] = Field(default=None, description="Targeted genders. Values: [\"unknown\",\"male\",\"female\"]. If the GENDER field is missing, the default behavior in terms of ad delivery is that **All genders will be targeted**.", alias="GENDER")
    geo: Optional[List[StrictStr]] = Field(default=None, description="Location region codes, e.g., \"BE-VOV\" (East Flanders, Belgium) For complete list, <a href=\"https://help.pinterest.com/sub/helpcenter/partner/pinterest_location_targeting_codes.xlsx\" target=\"_blank\">click here</a> or postal codes, e.g., \"US-94107\". Use either region codes or postal codes but not both. At least one of LOCATION or GEO must be specified. If the GEO field is missing, then only LOCATION values will be targeted (see LOCATION field below).", alias="GEO")
    interest: Optional[List[StrictStr]] = Field(default=None, description="Array of interest object IDs. If the INTEREST field is missing, the default behavior in terms of ad delivery is that **All interests will be targeted**.", alias="INTEREST")
    locale: Optional[List[StrictStr]] = Field(default=None, description="24 ISO 639-1 two-letter language codes. If the LOCALE field is not included in the request, all languages are targeted.", alias="LOCALE")
    location: Optional[List[StrictStr]] = Field(default=None, description="22 ISO Alpha 2 two letter country codes or US Nielsen DMA (Designated Market Area) codes (location region codes) (e.g., [\"US\", \"807\"]). For complete list, <a href=\"https://help.pinterest.com/sub/helpcenter/partner/pinterest_location_targeting_codes.xlsx\" target=\"_blank\">click here</a>. Location-Country and Location-Metro codes apply. At least one of LOCATION or GEO must be specified. If the LOCATION field is missing, then only GEO values will be targeted (see GEO field above).", alias="LOCATION")
    maximum_age: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Maximum age to target (inclusive). Values: \"18\", \"19\", ..., \"65\", \"65+\". Must be used together with `MINIMUM_AGE`. Cannot be combined with `AGE_BUCKET`. If neither `MINIMUM_AGE`/`MAXIMUM_AGE` nor `AGE_BUCKET` are specified, all ages will be targeted.", alias="MAXIMUM_AGE")
    minimum_age: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Minimum age to target (inclusive). Values: \"18\", \"19\", ..., \"65\". Note: 65+ is not allowed for minimum age. Must be used together with `MAXIMUM_AGE`. Cannot be combined with `AGE_BUCKET`. If neither `MINIMUM_AGE`/`MAXIMUM_AGE` nor `AGE_BUCKET` are specified, all ages will be targeted.", alias="MINIMUM_AGE")
    shopping_retargeting: Optional[List[TargetingSpecShoppingRetargeting]] = Field(default=None, description="Array of object: lookback_window [Integer]: Number of days ago to start lookback timeframe for dynamic retargeting tag_types [Array of integer]: Event types to target for dynamic retargeting exclusion_window [Integer]: Number of days ago to stop lookback timeframe for dynamic retargeting", alias="SHOPPING_RETARGETING")
    targeting_strategy: Optional[List[StrictStr]] = Field(default=None, alias="TARGETING_STRATEGY")
    __properties: ClassVar[List[str]] = ["AGE_BUCKET", "APPTYPE", "AUDIENCE_EXCLUDE", "AUDIENCE_INCLUDE", "GENDER", "GEO", "INTEREST", "LOCALE", "LOCATION", "MAXIMUM_AGE", "MINIMUM_AGE", "SHOPPING_RETARGETING", "TARGETING_STRATEGY"]

    @field_validator('maximum_age')
    def maximum_age_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if value is None:
            return value

        if not re.match(r"^\d+\+?$", value):
            raise ValueError(r"must validate the regular expression /^\d+\+?$/")
        return value

    @field_validator('minimum_age')
    def minimum_age_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if value is None:
            return value

        if not re.match(r"^\d+$", value):
            raise ValueError(r"must validate the regular expression /^\d+$/")
        return value

    @field_validator('targeting_strategy')
    def targeting_strategy_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        for i in value:
            if i not in set(['CHOOSE_YOUR_OWN', 'FIND_NEW_CUSTOMERS', 'RECONNECT_WITH_USERS']):
                raise ValueError("each list item must be one of ('CHOOSE_YOUR_OWN', 'FIND_NEW_CUSTOMERS', 'RECONNECT_WITH_USERS')")
        return value

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

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

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of each item in shopping_retargeting (list)
        _items = []
        if self.shopping_retargeting:
            for _item_shopping_retargeting in self.shopping_retargeting:
                if _item_shopping_retargeting:
                    _items.append(_item_shopping_retargeting.to_dict())
            _dict['SHOPPING_RETARGETING'] = _items
        # set to None if age_bucket (nullable) is None
        # and model_fields_set contains the field
        if self.age_bucket is None and "age_bucket" in self.model_fields_set:
            _dict['AGE_BUCKET'] = None

        # set to None if apptype (nullable) is None
        # and model_fields_set contains the field
        if self.apptype is None and "apptype" in self.model_fields_set:
            _dict['APPTYPE'] = None

        # set to None if audience_exclude (nullable) is None
        # and model_fields_set contains the field
        if self.audience_exclude is None and "audience_exclude" in self.model_fields_set:
            _dict['AUDIENCE_EXCLUDE'] = None

        # set to None if audience_include (nullable) is None
        # and model_fields_set contains the field
        if self.audience_include is None and "audience_include" in self.model_fields_set:
            _dict['AUDIENCE_INCLUDE'] = None

        # set to None if gender (nullable) is None
        # and model_fields_set contains the field
        if self.gender is None and "gender" in self.model_fields_set:
            _dict['GENDER'] = None

        # set to None if geo (nullable) is None
        # and model_fields_set contains the field
        if self.geo is None and "geo" in self.model_fields_set:
            _dict['GEO'] = None

        # set to None if locale (nullable) is None
        # and model_fields_set contains the field
        if self.locale is None and "locale" in self.model_fields_set:
            _dict['LOCALE'] = None

        # set to None if location (nullable) is None
        # and model_fields_set contains the field
        if self.location is None and "location" in self.model_fields_set:
            _dict['LOCATION'] = None

        # set to None if shopping_retargeting (nullable) is None
        # and model_fields_set contains the field
        if self.shopping_retargeting is None and "shopping_retargeting" in self.model_fields_set:
            _dict['SHOPPING_RETARGETING'] = None

        # set to None if targeting_strategy (nullable) is None
        # and model_fields_set contains the field
        if self.targeting_strategy is None and "targeting_strategy" in self.model_fields_set:
            _dict['TARGETING_STRATEGY'] = None

        return _dict

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

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

        _obj = cls.model_validate({
            "AGE_BUCKET": obj.get("AGE_BUCKET"),
            "APPTYPE": obj.get("APPTYPE"),
            "AUDIENCE_EXCLUDE": obj.get("AUDIENCE_EXCLUDE"),
            "AUDIENCE_INCLUDE": obj.get("AUDIENCE_INCLUDE"),
            "GENDER": obj.get("GENDER"),
            "GEO": obj.get("GEO"),
            "INTEREST": obj.get("INTEREST"),
            "LOCALE": obj.get("LOCALE"),
            "LOCATION": obj.get("LOCATION"),
            "MAXIMUM_AGE": obj.get("MAXIMUM_AGE"),
            "MINIMUM_AGE": obj.get("MINIMUM_AGE"),
            "SHOPPING_RETARGETING": [TargetingSpecShoppingRetargeting.from_dict(_item) for _item in obj["SHOPPING_RETARGETING"]] if obj.get("SHOPPING_RETARGETING") is not None else None,
            "TARGETING_STRATEGY": obj.get("TARGETING_STRATEGY")
        })
        return _obj


