# coding: utf-8

"""
Perigon API

The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key.

The version of the OpenAPI document: 1.0.0
Contact: data@perigon.io
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, Union

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

from perigon.models.category_holder import CategoryHolder
from perigon.models.category_with_score_holder import CategoryWithScoreHolder
from perigon.models.company_holder import CompanyHolder
from perigon.models.entity_holder import EntityHolder
from perigon.models.event_type_holder import EventTypeHolder
from perigon.models.id_name_holder import IdNameHolder
from perigon.models.journalist import Journalist
from perigon.models.keyword_holder import KeywordHolder
from perigon.models.label_holder import LabelHolder
from perigon.models.location_holder import LocationHolder
from perigon.models.person_holder import PersonHolder
from perigon.models.place import Place
from perigon.models.sentiment_holder import SentimentHolder
from perigon.models.source_holder import SourceHolder
from perigon.models.topic_holder import TopicHolder


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

    url: Optional[StrictStr] = None
    authors_byline: Optional[StrictStr] = Field(default=None, alias="authorsByline")
    article_id: Optional[StrictStr] = Field(default=None, alias="articleId")
    cluster_id: Optional[StrictStr] = Field(default=None, alias="clusterId")
    source: Optional[SourceHolder] = None
    image_url: Optional[StrictStr] = Field(default=None, alias="imageUrl")
    country: Optional[StrictStr] = None
    language: Optional[StrictStr] = None
    pub_date: Optional[StrictStr] = Field(default=None, alias="pubDate")
    add_date: Optional[StrictStr] = Field(default=None, alias="addDate")
    refresh_date: Optional[StrictStr] = Field(default=None, alias="refreshDate")
    score: Optional[Union[StrictFloat, StrictInt]] = None
    title: Optional[StrictStr] = None
    description: Optional[StrictStr] = None
    content: Optional[StrictStr] = None
    en_content_word_count: Optional[StrictInt] = Field(
        default=None, alias="enContentWordCount"
    )
    medium: Optional[StrictStr] = None
    links: Optional[List[StrictStr]] = None
    labels: Optional[List[LabelHolder]] = None
    event_types: Optional[List[EventTypeHolder]] = Field(
        default=None, alias="eventTypes"
    )
    matched_authors: Optional[List[IdNameHolder]] = Field(
        default=None, alias="matchedAuthors"
    )
    claim: Optional[StrictStr] = None
    verdict: Optional[StrictStr] = None
    keywords: Optional[List[KeywordHolder]] = None
    topics: Optional[List[TopicHolder]] = None
    categories: Optional[List[CategoryHolder]] = None
    taxonomies: Optional[List[CategoryWithScoreHolder]] = None
    entities: Optional[List[EntityHolder]] = None
    companies: Optional[List[CompanyHolder]] = None
    sentiment: Optional[SentimentHolder] = None
    summary: Optional[StrictStr] = None
    short_summary: Optional[StrictStr] = Field(default=None, alias="shortSummary")
    translation: Optional[StrictStr] = None
    translated_title: Optional[StrictStr] = Field(default=None, alias="translatedTitle")
    translated_description: Optional[StrictStr] = Field(
        default=None, alias="translatedDescription"
    )
    translated_summary: Optional[StrictStr] = Field(
        default=None, alias="translatedSummary"
    )
    locations: Optional[List[LocationHolder]] = None
    reprint: Optional[StrictBool] = None
    reprint_group_id: Optional[StrictStr] = Field(default=None, alias="reprintGroupId")
    places: Optional[List[Place]] = None
    people: Optional[List[PersonHolder]] = None
    cluster: Optional[NewsCluster] = None
    journalists: Optional[List[Journalist]] = None
    highlights: Optional[Dict[str, List[StrictStr]]] = None
    __properties: ClassVar[List[str]] = [
        "url",
        "authorsByline",
        "articleId",
        "clusterId",
        "source",
        "imageUrl",
        "country",
        "language",
        "pubDate",
        "addDate",
        "refreshDate",
        "score",
        "title",
        "description",
        "content",
        "enContentWordCount",
        "medium",
        "links",
        "labels",
        "eventTypes",
        "matchedAuthors",
        "claim",
        "verdict",
        "keywords",
        "topics",
        "categories",
        "taxonomies",
        "entities",
        "companies",
        "sentiment",
        "summary",
        "shortSummary",
        "translation",
        "translatedTitle",
        "translatedDescription",
        "translatedSummary",
        "locations",
        "reprint",
        "reprintGroupId",
        "places",
        "people",
        "cluster",
        "journalists",
        "highlights",
    ]

    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 Article 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 source
        if self.source:
            _dict["source"] = self.source.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in labels (list)
        _items = []
        if self.labels:
            for _item_labels in self.labels:
                if _item_labels:
                    _items.append(_item_labels.to_dict())
            _dict["labels"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in event_types (list)
        _items = []
        if self.event_types:
            for _item_event_types in self.event_types:
                if _item_event_types:
                    _items.append(_item_event_types.to_dict())
            _dict["eventTypes"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in matched_authors (list)
        _items = []
        if self.matched_authors:
            for _item_matched_authors in self.matched_authors:
                if _item_matched_authors:
                    _items.append(_item_matched_authors.to_dict())
            _dict["matchedAuthors"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in keywords (list)
        _items = []
        if self.keywords:
            for _item_keywords in self.keywords:
                if _item_keywords:
                    _items.append(_item_keywords.to_dict())
            _dict["keywords"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in topics (list)
        _items = []
        if self.topics:
            for _item_topics in self.topics:
                if _item_topics:
                    _items.append(_item_topics.to_dict())
            _dict["topics"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in categories (list)
        _items = []
        if self.categories:
            for _item_categories in self.categories:
                if _item_categories:
                    _items.append(_item_categories.to_dict())
            _dict["categories"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in taxonomies (list)
        _items = []
        if self.taxonomies:
            for _item_taxonomies in self.taxonomies:
                if _item_taxonomies:
                    _items.append(_item_taxonomies.to_dict())
            _dict["taxonomies"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in entities (list)
        _items = []
        if self.entities:
            for _item_entities in self.entities:
                if _item_entities:
                    _items.append(_item_entities.to_dict())
            _dict["entities"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in companies (list)
        _items = []
        if self.companies:
            for _item_companies in self.companies:
                if _item_companies:
                    _items.append(_item_companies.to_dict())
            _dict["companies"] = _items
        # override the default output from pydantic by calling `to_dict()` of sentiment
        if self.sentiment:
            _dict["sentiment"] = self.sentiment.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in locations (list)
        _items = []
        if self.locations:
            for _item_locations in self.locations:
                if _item_locations:
                    _items.append(_item_locations.to_dict())
            _dict["locations"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in places (list)
        _items = []
        if self.places:
            for _item_places in self.places:
                if _item_places:
                    _items.append(_item_places.to_dict())
            _dict["places"] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in people (list)
        _items = []
        if self.people:
            for _item_people in self.people:
                if _item_people:
                    _items.append(_item_people.to_dict())
            _dict["people"] = _items
        # override the default output from pydantic by calling `to_dict()` of cluster
        if self.cluster:
            _dict["cluster"] = self.cluster.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in journalists (list)
        _items = []
        if self.journalists:
            for _item_journalists in self.journalists:
                if _item_journalists:
                    _items.append(_item_journalists.to_dict())
            _dict["journalists"] = _items
        # set to None if url (nullable) is None
        # and model_fields_set contains the field
        if self.url is None and "url" in self.model_fields_set:
            _dict["url"] = None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return _dict

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

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

        _obj = cls.model_validate(
            {
                "url": obj.get("url"),
                "authorsByline": obj.get("authorsByline"),
                "articleId": obj.get("articleId"),
                "clusterId": obj.get("clusterId"),
                "source": (
                    SourceHolder.from_dict(obj["source"])
                    if obj.get("source") is not None
                    else None
                ),
                "imageUrl": obj.get("imageUrl"),
                "country": obj.get("country"),
                "language": obj.get("language"),
                "pubDate": obj.get("pubDate"),
                "addDate": obj.get("addDate"),
                "refreshDate": obj.get("refreshDate"),
                "score": obj.get("score"),
                "title": obj.get("title"),
                "description": obj.get("description"),
                "content": obj.get("content"),
                "enContentWordCount": obj.get("enContentWordCount"),
                "medium": obj.get("medium"),
                "links": obj.get("links"),
                "labels": (
                    [LabelHolder.from_dict(_item) for _item in obj["labels"]]
                    if obj.get("labels") is not None
                    else None
                ),
                "eventTypes": (
                    [EventTypeHolder.from_dict(_item) for _item in obj["eventTypes"]]
                    if obj.get("eventTypes") is not None
                    else None
                ),
                "matchedAuthors": (
                    [IdNameHolder.from_dict(_item) for _item in obj["matchedAuthors"]]
                    if obj.get("matchedAuthors") is not None
                    else None
                ),
                "claim": obj.get("claim"),
                "verdict": obj.get("verdict"),
                "keywords": (
                    [KeywordHolder.from_dict(_item) for _item in obj["keywords"]]
                    if obj.get("keywords") is not None
                    else None
                ),
                "topics": (
                    [TopicHolder.from_dict(_item) for _item in obj["topics"]]
                    if obj.get("topics") is not None
                    else None
                ),
                "categories": (
                    [CategoryHolder.from_dict(_item) for _item in obj["categories"]]
                    if obj.get("categories") is not None
                    else None
                ),
                "taxonomies": (
                    [
                        CategoryWithScoreHolder.from_dict(_item)
                        for _item in obj["taxonomies"]
                    ]
                    if obj.get("taxonomies") is not None
                    else None
                ),
                "entities": (
                    [EntityHolder.from_dict(_item) for _item in obj["entities"]]
                    if obj.get("entities") is not None
                    else None
                ),
                "companies": (
                    [CompanyHolder.from_dict(_item) for _item in obj["companies"]]
                    if obj.get("companies") is not None
                    else None
                ),
                "sentiment": (
                    SentimentHolder.from_dict(obj["sentiment"])
                    if obj.get("sentiment") is not None
                    else None
                ),
                "summary": obj.get("summary"),
                "shortSummary": obj.get("shortSummary"),
                "translation": obj.get("translation"),
                "translatedTitle": obj.get("translatedTitle"),
                "translatedDescription": obj.get("translatedDescription"),
                "translatedSummary": obj.get("translatedSummary"),
                "locations": (
                    [LocationHolder.from_dict(_item) for _item in obj["locations"]]
                    if obj.get("locations") is not None
                    else None
                ),
                "reprint": obj.get("reprint"),
                "reprintGroupId": obj.get("reprintGroupId"),
                "places": (
                    [Place.from_dict(_item) for _item in obj["places"]]
                    if obj.get("places") is not None
                    else None
                ),
                "people": (
                    [PersonHolder.from_dict(_item) for _item in obj["people"]]
                    if obj.get("people") is not None
                    else None
                ),
                "cluster": (
                    NewsCluster.from_dict(obj["cluster"])
                    if obj.get("cluster") is not None
                    else None
                ),
                "journalists": (
                    [Journalist.from_dict(_item) for _item in obj["journalists"]]
                    if obj.get("journalists") is not None
                    else None
                ),
                "highlights": obj.get("highlights"),
            }
        )
        return _obj


from perigon.models.news_cluster import NewsCluster

# TODO: Rewrite to not use raise_errors
Article.model_rebuild(raise_errors=False)
