# coding: utf-8

"""
    Klaviyo API

    The Klaviyo REST API. Please visit https://developers.klaviyo.com for more details.

    Contact: developers@klaviyo.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, StrictBool, StrictInt, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from openapi_client.models.dynamic_button import DynamicButton
from openapi_client.models.step import Step
from openapi_client.models.teaser import Teaser
from openapi_client.models.version_properties import VersionProperties
from openapi_client.models.version_styles import VersionStyles
from typing import Optional, Set
from typing_extensions import Self

class Version(BaseModel):
    """
    Version
    """ # noqa: E501
    id: Optional[StrictInt] = None
    steps: List[Step]
    triggers: Optional[List[Dict[str, Any]]] = None
    teasers: Optional[List[Teaser]] = None
    dynamic_button: Optional[DynamicButton] = None
    name: Optional[StrictStr] = None
    styles: Optional[VersionStyles] = None
    properties: Optional[VersionProperties] = None
    type: Optional[StrictStr] = Field(default='popup', description="Form type enumeration.")
    location: Optional[StrictStr] = Field(default=None, description="Display location enumeration.")
    status: Optional[StrictStr] = Field(default='draft', description="Form status enumeration.")
    ab_test: Optional[StrictBool] = False
    specialties: Optional[List[StrictStr]] = None
    __properties: ClassVar[List[str]] = ["id", "steps", "triggers", "teasers", "dynamic_button", "name", "styles", "properties", "type", "location", "status", "ab_test", "specialties"]

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

        if value not in set(['banner', 'embed', 'flyout', 'full_screen', 'popup']):
            raise ValueError("must be one of enum values ('banner', 'embed', 'flyout', 'full_screen', 'popup')")
        return value

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

        if value not in set(['bottom_center', 'bottom_left', 'bottom_right', 'center_left', 'center_right', 'top_center', 'top_left', 'top_right']):
            raise ValueError("must be one of enum values ('bottom_center', 'bottom_left', 'bottom_right', 'center_left', 'center_right', 'top_center', 'top_left', 'top_right')")
        return value

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

        if value not in set(['draft', 'live']):
            raise ValueError("must be one of enum values ('draft', 'live')")
        return value

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

        for i in value:
            if i not in set(['BACK_IN_STOCK']):
                raise ValueError("each list item must be one of ('BACK_IN_STOCK')")
        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 Version 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 steps (list)
        _items = []
        if self.steps:
            for _item in self.steps:
                if _item:
                    _items.append(_item.to_dict())
            _dict['steps'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in teasers (list)
        _items = []
        if self.teasers:
            for _item in self.teasers:
                if _item:
                    _items.append(_item.to_dict())
            _dict['teasers'] = _items
        # override the default output from pydantic by calling `to_dict()` of dynamic_button
        if self.dynamic_button:
            _dict['dynamic_button'] = self.dynamic_button.to_dict()
        # override the default output from pydantic by calling `to_dict()` of styles
        if self.styles:
            _dict['styles'] = self.styles.to_dict()
        # override the default output from pydantic by calling `to_dict()` of properties
        if self.properties:
            _dict['properties'] = self.properties.to_dict()
        # set to None if id (nullable) is None
        # and model_fields_set contains the field
        if self.id is None and "id" in self.model_fields_set:
            _dict['id'] = None

        # set to None if name (nullable) is None
        # and model_fields_set contains the field
        if self.name is None and "name" in self.model_fields_set:
            _dict['name'] = 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

        return _dict

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

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

        _obj = cls.model_validate({
            "id": obj.get("id"),
            "steps": [Step.from_dict(_item) for _item in obj["steps"]] if obj.get("steps") is not None else None,
            "triggers": obj.get("triggers"),
            "teasers": [Teaser.from_dict(_item) for _item in obj["teasers"]] if obj.get("teasers") is not None else None,
            "dynamic_button": DynamicButton.from_dict(obj["dynamic_button"]) if obj.get("dynamic_button") is not None else None,
            "name": obj.get("name"),
            "styles": VersionStyles.from_dict(obj["styles"]) if obj.get("styles") is not None else None,
            "properties": VersionProperties.from_dict(obj["properties"]) if obj.get("properties") is not None else None,
            "type": obj.get("type") if obj.get("type") is not None else 'popup',
            "location": obj.get("location"),
            "status": obj.get("status") if obj.get("status") is not None else 'draft',
            "ab_test": obj.get("ab_test") if obj.get("ab_test") is not None else False,
            "specialties": obj.get("specialties")
        })
        return _obj


