# 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 datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from pinterestsdk.models.board_owner import BoardOwner
from pinterestsdk.models.creative_type import CreativeType
from pinterestsdk.models.pin_media import PinMedia
from typing import Optional, Set
from typing_extensions import Self

class Pin(BaseModel):
    """
    Pin model containing properties related to a Pinterest Pin.
    """ # noqa: E501
    alt_text: Optional[Annotated[str, Field(strict=True, max_length=500)]] = None
    board_id: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="The board to which this Pin belongs.")
    board_owner: Optional[BoardOwner] = None
    board_section_id: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="The board section to which this Pin belongs.")
    created_at: Optional[datetime] = None
    creative_type: Optional[CreativeType] = None
    description: Optional[Annotated[str, Field(strict=True, max_length=800)]] = None
    dominant_color: Optional[StrictStr] = Field(default=None, description="Dominant pin color. Hex number, e.g. `#6E7874`.")
    has_been_promoted: Optional[StrictBool] = Field(default=None, description="Whether the Pin has been promoted or not.")
    id: Annotated[str, Field(strict=True)]
    is_owner: Optional[StrictBool] = Field(default=None, description="Whether the \"operation user_account\" is the Pin owner.")
    is_standard: Optional[StrictBool] = Field(default=None, description="Whether the Pin is standard or not. See documentation on [Changes to Pin creation](/docs/api-features/content-overview/) for more information.")
    link: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = None
    media: Optional[PinMedia] = None
    parent_pin_id: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="The source pin id if this pin was saved from another pin. [Learn more](https://help.pinterest.com/article/save-pins-on-pinterest).")
    pin_metrics: Optional[Dict[str, Any]] = Field(default=None, description="Pin metrics with associated time intervals if any.")
    title: Optional[Annotated[str, Field(strict=True, max_length=100)]] = None
    __properties: ClassVar[List[str]] = ["alt_text", "board_id", "board_owner", "board_section_id", "created_at", "creative_type", "description", "dominant_color", "has_been_promoted", "id", "is_owner", "is_standard", "link", "media", "parent_pin_id", "pin_metrics", "title"]

    @field_validator('board_id')
    def board_id_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('board_section_id')
    def board_section_id_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('id')
    def id_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if not re.match(r"^\d+$", value):
            raise ValueError(r"must validate the regular expression /^\d+$/")
        return value

    @field_validator('parent_pin_id')
    def parent_pin_id_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

    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 Pin 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.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        * OpenAPI `readOnly` fields are excluded.
        """
        excluded_fields: Set[str] = set([
            "board_owner",
            "created_at",
            "creative_type",
            "has_been_promoted",
            "is_owner",
            "is_standard",
            "media",
            "pin_metrics",
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of board_owner
        if self.board_owner:
            _dict['board_owner'] = self.board_owner.to_dict()
        # override the default output from pydantic by calling `to_dict()` of media
        if self.media:
            _dict['media'] = self.media.to_dict()
        # set to None if alt_text (nullable) is None
        # and model_fields_set contains the field
        if self.alt_text is None and "alt_text" in self.model_fields_set:
            _dict['alt_text'] = None

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

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

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

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

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

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

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

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

        return _dict

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

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

        _obj = cls.model_validate({
            "alt_text": obj.get("alt_text"),
            "board_id": obj.get("board_id"),
            "board_owner": BoardOwner.from_dict(obj["board_owner"]) if obj.get("board_owner") is not None else None,
            "board_section_id": obj.get("board_section_id"),
            "created_at": obj.get("created_at"),
            "creative_type": obj.get("creative_type"),
            "description": obj.get("description"),
            "dominant_color": obj.get("dominant_color"),
            "has_been_promoted": obj.get("has_been_promoted"),
            "id": obj.get("id"),
            "is_owner": obj.get("is_owner"),
            "is_standard": obj.get("is_standard"),
            "link": obj.get("link"),
            "media": PinMedia.from_dict(obj["media"]) if obj.get("media") is not None else None,
            "parent_pin_id": obj.get("parent_pin_id"),
            "pin_metrics": obj.get("pin_metrics"),
            "title": obj.get("title")
        })
        return _obj


