# coding: utf-8

"""
Mozart platform API

API for interacting with the Mozart platform.

The version of the OpenAPI document: 0.2.0
Contact: support@bang-olufsen.dk
Generated by OpenAPI Generator (https://openapi-generator.tech)

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

from __future__ import annotations

import json
import pprint
import re  # noqa: F401
from typing import Any, ClassVar, Dict, List, Optional, Set
from uuid import UUID

from pydantic import (
    BaseModel,
    ConfigDict,
    Field,
    StrictBool,
    StrictInt,
    StrictStr,
    field_validator,
)
from typing_extensions import Annotated, Self

from mozart_api.models.art import Art
from mozart_api.models.beolink_leader import BeolinkLeader


class PlaybackContentMetadata(BaseModel):
    """
    PlaybackContentMetadata
    """  # noqa: E501

    album_name: Annotated[Optional[StrictStr], Field(alias="albumName")] = None
    art: Optional[List[Art]] = None
    artist_name: Annotated[Optional[StrictStr], Field(alias="artistName")] = None
    bitdepth: Optional[StrictInt] = None
    bitrate: Optional[StrictInt] = None
    container_name: Annotated[Optional[StrictStr], Field(alias="containerName")] = None
    encoding: Optional[StrictStr] = None
    genre: Optional[StrictStr] = None
    id: Optional[StrictInt] = None
    input_channel_processing: Annotated[
        Optional[StrictStr],
        Field(
            description="Input processing/decoding on top of the base codec indicated in encoding. E.g. Dolby Atmos on top of Dolby TrueHD or Dolby Surround on top of PCM. For Dolby, this value has priority over encoding, meaning that if inputChannelProcessing has a value, it must be indicated in the app, and optionally the encoding value can be indicated as well. If inputChannelProcessing does not have value the encoding value must be indicated. ",
            alias="inputChannelProcessing",
        ),
    ] = None
    input_channels: Annotated[
        Optional[StrictStr], Field(description="e.g. 5.1", alias="inputChannels")
    ] = None
    is_explicit: Annotated[Optional[StrictBool], Field(alias="isExplicit")] = None
    organization: Annotated[
        Optional[StrictStr],
        Field(
            description='This can be filled by gstreamer\'s GST_TAG_ORGANIZATION. Mozart can also fill this with netradio station name like "P3" and TV content like "Netflix". This is needed so it\'s possible to show who the provider is for the playing audio track/content. '
        ),
    ] = None
    output_channel_processing: Annotated[
        Optional[StrictStr],
        Field(description="e.g. downmix", alias="outputChannelProcessing"),
    ] = None
    output_channels: Annotated[
        Optional[StrictStr], Field(description="e.g. 7.1", alias="outputChannels")
    ] = None
    queue_id: Annotated[Optional[UUID], Field(alias="queueId")] = None
    remote_leader: Annotated[Optional[BeolinkLeader], Field(alias="remoteLeader")] = (
        None
    )
    remote_source: Annotated[Optional[StrictStr], Field(alias="remoteSource")] = None
    samplerate: Optional[StrictInt] = None
    source: Optional[StrictStr] = None
    source_internal_id: Annotated[
        Optional[StrictStr], Field(alias="sourceInternalId")
    ] = None
    tags: Optional[List[StrictStr]] = None
    title: Optional[StrictStr] = None
    total_duration: Annotated[
        Optional[StrictInt],
        Field(
            description="to be removed once all devices and apps are updated",
            alias="totalDuration",
        ),
    ] = None
    total_duration_seconds: Annotated[
        Optional[StrictInt], Field(alias="totalDurationSeconds")
    ] = None
    track: Optional[StrictInt] = None
    track_count: Annotated[Optional[StrictInt], Field(alias="trackCount")] = None
    uri: Optional[StrictStr] = None
    __properties: ClassVar[List[str]] = [
        "albumName",
        "art",
        "artistName",
        "bitdepth",
        "bitrate",
        "containerName",
        "encoding",
        "genre",
        "id",
        "inputChannelProcessing",
        "inputChannels",
        "isExplicit",
        "organization",
        "outputChannelProcessing",
        "outputChannels",
        "queueId",
        "remoteLeader",
        "remoteSource",
        "samplerate",
        "source",
        "sourceInternalId",
        "tags",
        "title",
        "totalDuration",
        "totalDurationSeconds",
        "track",
        "trackCount",
        "uri",
    ]

    @field_validator("encoding")
    def encoding_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set([
            "pcm",
            "wav",
            "mp3",
            "oggvorbis",
            "aac",
            "flac",
            "sbc",
            "alac",
            "opus",
            "DolbyDigital",
            "DolbyDigitalPlus",
            "DolbyTrueHD",
            "unknown",
        ]):
            raise ValueError(
                "must be one of enum values ('pcm', 'wav', 'mp3', 'oggvorbis', 'aac', 'flac', 'sbc', 'alac', 'opus', 'DolbyDigital', 'DolbyDigitalPlus', 'DolbyTrueHD', 'unknown')"
            )
        return value

    @field_validator("input_channel_processing")
    def input_channel_processing_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

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

    @field_validator("output_channel_processing")
    def output_channel_processing_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(["Direct", "Downmix", "TrueImage", "DolbyMode"]):
            raise ValueError(
                "must be one of enum values ('Direct', 'Downmix', 'TrueImage', 'DolbyMode')"
            )
        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 PlaybackContentMetadata 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 art (list)
        _items = []
        if self.art:
            for _item_art in self.art:
                if _item_art:
                    _items.append(_item_art.to_dict())
            _dict["art"] = _items
        # override the default output from pydantic by calling `to_dict()` of remote_leader
        if self.remote_leader:
            _dict["remoteLeader"] = self.remote_leader.to_dict()
        # set to None if input_channel_processing (nullable) is None
        # and model_fields_set contains the field
        if (
            self.input_channel_processing is None
            and "input_channel_processing" in self.model_fields_set
        ):
            _dict["inputChannelProcessing"] = None

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

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

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

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

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

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

        return _dict

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

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

        _obj = cls.model_validate({
            "albumName": obj.get("albumName"),
            "art": [Art.from_dict(_item) for _item in obj["art"]]
            if obj.get("art") is not None
            else None,
            "artistName": obj.get("artistName"),
            "bitdepth": obj.get("bitdepth"),
            "bitrate": obj.get("bitrate"),
            "containerName": obj.get("containerName"),
            "encoding": obj.get("encoding"),
            "genre": obj.get("genre"),
            "id": obj.get("id"),
            "inputChannelProcessing": obj.get("inputChannelProcessing"),
            "inputChannels": obj.get("inputChannels"),
            "isExplicit": obj.get("isExplicit"),
            "organization": obj.get("organization"),
            "outputChannelProcessing": obj.get("outputChannelProcessing"),
            "outputChannels": obj.get("outputChannels"),
            "queueId": obj.get("queueId"),
            "remoteLeader": BeolinkLeader.from_dict(obj["remoteLeader"])
            if obj.get("remoteLeader") is not None
            else None,
            "remoteSource": obj.get("remoteSource"),
            "samplerate": obj.get("samplerate"),
            "source": obj.get("source"),
            "sourceInternalId": obj.get("sourceInternalId"),
            "tags": obj.get("tags"),
            "title": obj.get("title"),
            "totalDuration": obj.get("totalDuration"),
            "totalDurationSeconds": obj.get("totalDurationSeconds"),
            "track": obj.get("track"),
            "trackCount": obj.get("trackCount"),
            "uri": obj.get("uri"),
        })
        return _obj
