# coding: utf-8

"""
    Verity471 Unified API

      - creds: 1.0.1
  - indicators: 1.0.0
  - malware: 1.0.0
  - reports: 1.0.0
  - sources: 1.0.2
  - actors: 1.0.1
  - watchers: 1.0.0
  - observables: 1.0.0
  - entities: 1.0.0
  - girs: 1.0.0


    The version of the OpenAPI document: 1.1.1
    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, StrictInt, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from verity471.models.activity import Activity
from verity471.models.classification import Classification
from verity471.models.indicator_data import IndicatorData
from verity471.models.kill_chain_phase import KillChainPhase
from verity471.models.revocation import Revocation
from verity471.models.threat import Threat
from typing import Optional, Set, TYPE_CHECKING
from typing_extensions import Self

if TYPE_CHECKING:
    # Only for type checkers; does not run at runtime.
    from verity471.verity_stix import STIXMapperSettings


class IntegrationsIndicator(BaseModel):
    """
    Indicator data
    """ # noqa: E501
    activity: Optional[Activity] = Field(default=None, description="Activity information related to the entity")
    classification: Optional[Classification] = Field(default=None, description="Classification information for the entity")
    confidence: Optional[StrictInt] = Field(default=None, description="Confidence score for the indicator (0-100)")
    data: Optional[IndicatorData] = Field(default=None, description="Indicator data containing specific details")
    description: Optional[StrictStr] = Field(default=None, description="Descriptive information about the indicator")
    expiration_ts: Optional[datetime] = Field(default=None, description="Timestamp when the indicator expires")
    id: Optional[StrictStr] = Field(default=None, description="Unique identifier of the entity")
    kill_chain_phases: Optional[List[KillChainPhase]] = Field(default=None, description="List of kill chain phases associated with the entity")
    pattern: Optional[StrictStr] = Field(default=None, description="Pattern string for the indicator")
    pattern_type: Optional[StrictStr] = Field(default=None, description="Type of pattern used for the indicator")
    pattern_version: Optional[StrictStr] = Field(default=None, description="Version of the pattern specification")
    revocation: Optional[Revocation] = Field(default=None, description="Revocation information for the indicator, if applicable")
    threat: Optional[Threat] = Field(default=None, description="Threat information associated with the entity")
    type: Optional[StrictStr] = Field(default=None, description="Type of indicator")
    __properties: ClassVar[List[str]] = ["activity", "classification", "confidence", "data", "description", "expiration_ts", "id", "kill_chain_phases", "pattern", "pattern_type", "pattern_version", "revocation", "threat", "type"]

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

        if value not in set(['domain', 'email', 'file', 'ipv4', 'url', 'yara']):
            raise ValueError("must be one of enum values ('domain', 'email', 'file', 'ipv4', 'url', 'yara')")
        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_stix(self, settings: Optional["STIXMapperSettings"] = None):
        try:
            from verity471.verity_stix.mappers.common import StixMapper
        except ImportError as e:
            raise ImportError(
                "STIX support is an optional feature. "
                "Install with: pip install 'verity471[stix]'"
            ) from e
        stix_mapper = StixMapper(settings)
        return stix_mapper.map(self.to_dict())

    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 IntegrationsIndicator 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 activity
        if self.activity:
            _dict['activity'] = self.activity.to_dict()
        # override the default output from pydantic by calling `to_dict()` of classification
        if self.classification:
            _dict['classification'] = self.classification.to_dict()
        # override the default output from pydantic by calling `to_dict()` of data
        if self.data:
            _dict['data'] = self.data.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in kill_chain_phases (list)
        _items = []
        if self.kill_chain_phases:
            for _item_kill_chain_phases in self.kill_chain_phases:
                if _item_kill_chain_phases:
                    _items.append(_item_kill_chain_phases.to_dict())
            _dict['kill_chain_phases'] = _items
        # override the default output from pydantic by calling `to_dict()` of revocation
        if self.revocation:
            _dict['revocation'] = self.revocation.to_dict()
        # override the default output from pydantic by calling `to_dict()` of threat
        if self.threat:
            _dict['threat'] = self.threat.to_dict()
        return _dict

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

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

        _obj = cls.model_validate({
            "activity": Activity.from_dict(obj["activity"]) if obj.get("activity") is not None else None,
            "classification": Classification.from_dict(obj["classification"]) if obj.get("classification") is not None else None,
            "confidence": obj.get("confidence"),
            "data": IndicatorData.from_dict(obj["data"]) if obj.get("data") is not None else None,
            "description": obj.get("description"),
            "expiration_ts": obj.get("expiration_ts"),
            "id": obj.get("id"),
            "kill_chain_phases": [KillChainPhase.from_dict(_item) for _item in obj["kill_chain_phases"]] if obj.get("kill_chain_phases") is not None else None,
            "pattern": obj.get("pattern"),
            "pattern_type": obj.get("pattern_type"),
            "pattern_version": obj.get("pattern_version"),
            "revocation": Revocation.from_dict(obj["revocation"]) if obj.get("revocation") is not None else None,
            "threat": Threat.from_dict(obj["threat"]) if obj.get("threat") is not None else None,
            "type": obj.get("type")
        })
        return _obj


