# 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 perigon_sdk.models.category_holder import CategoryHolder
from perigon_sdk.models.category_with_score_holder import CategoryWithScoreHolder
from perigon_sdk.models.company_holder import CompanyHolder
from perigon_sdk.models.entity_holder import EntityHolder
from perigon_sdk.models.event_type_holder import EventTypeHolder
from perigon_sdk.models.id_name_holder import IdNameHolder
from perigon_sdk.models.journalist import Journalist
from perigon_sdk.models.keyword_holder import KeywordHolder
from perigon_sdk.models.label_holder import LabelHolder
from perigon_sdk.models.location_holder import LocationHolder
from perigon_sdk.models.person_holder import PersonHolder
from perigon_sdk.models.place import Place
from perigon_sdk.models.sentiment_holder import SentimentHolder
from perigon_sdk.models.source_holder import SourceHolder
from perigon_sdk.models.topic_holder import TopicHolder
from pydantic import (
    BaseModel,
    ConfigDict,
    Field,
    StrictBool,
    StrictFloat,
    StrictInt,
    StrictStr,
)
from typing_extensions import Self


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
    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",
        "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
        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"),
                "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_sdk.models.news_cluster import NewsCluster

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