# 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 pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from verity471.models.bot_settings import BotSettings
from verity471.models.controller_url import ControllerUrl
from verity471.models.encryption import Encryption
from verity471.models.event_controller import EventController
from verity471.models.file import File
from verity471.models.location import Location
from verity471.models.recipient_domain import RecipientDomain
from verity471.models.redirect import Redirect
from verity471.models.settings import Settings
from verity471.models.template import Template
from verity471.models.trigger import Trigger
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 EventData(BaseModel):
    """
    Malware event data.
    """ # noqa: E501
    arguments: Optional[List[StrictStr]] = Field(default=None, description="Arguments.")
    attack_targets: Optional[List[Dict[str, StrictStr]]] = Field(default=None, description="Attack targets.")
    attack_type: Optional[StrictStr] = Field(default=None, description="Attack type.")
    bot_settings: Optional[BotSettings] = Field(default=None, description="An object containing varying data types showing malware bot settings data. Contains any of but not limited the following fields: `exit_country`, `encryption`.")
    command: Optional[StrictStr] = Field(default=None, description="Command.")
    component_type: Optional[StrictStr] = Field(default=None, description="Type of component i.e. `CORE`.")
    config_file: Optional[File] = Field(default=None, description="Config file.")
    controller: Optional[EventController] = Field(default=None, description="Object containing the `url` and `ipv4` of a `controller`.")
    controllers: Optional[List[ControllerUrl]] = Field(default=None, description="An array of objects, each containing an individual controller's url.")
    encryption: Optional[List[Encryption]] = Field(default=None, description="An array of `encryption` meta data.")
    exfil_location: Optional[StrictStr] = Field(default=None, description="Contains the url location of the exfiltration event.")
    file: Optional[File] = Field(default=None, description="Object containing fields of the `file`'s hashes (`md5`, `sha1`, `sha256`) and file `type` and `size`.")
    function: Optional[StrictStr] = Field(default=None, description="Function name.")
    inject_type: Optional[StrictStr] = Field(default=None, description="Inject type.")
    location: Optional[Location] = Field(default=None, description="The `url` object of the location of the event.")
    parameters: Optional[List[Dict[str, StrictStr]]] = Field(default=None, description="Parameters.")
    plugin_name: Optional[StrictStr] = Field(default=None, description="Plugin's name.")
    plugin_type: Optional[StrictStr] = Field(default=None, description="Type of plugin. i.e. `REMOTE_ACCESS`, `CREDENTIAL_STEALER`, `OTHER`.")
    recipient_domains: Optional[List[RecipientDomain]] = Field(default=None, description="Recipient domains.")
    recipient_file: Optional[File] = Field(default=None, description="Recipient file.")
    redirects: Optional[List[Redirect]] = Field(default=None, description="An array of redirects.")
    senders: Optional[List[StrictStr]] = Field(default=None, description="Senders.")
    service_type: Optional[StrictStr] = Field(default=None, description="Type of service.")
    settings: Optional[Settings] = Field(default=None, description="An array of event related `settings` objects containing any of but not limited the following fields: `plugin_location`, `bot_version`, `compaign_id`, etc.")
    target_type: Optional[StrictStr] = Field(default=None, description="Type of target.")
    template: Optional[Template] = Field(default=None, description="Template information.")
    triggers: Optional[List[Trigger]] = Field(default=None, description="An array of objects, each containing the field `trigger`.")
    __properties: ClassVar[List[str]] = ["arguments", "attack_targets", "attack_type", "bot_settings", "command", "component_type", "config_file", "controller", "controllers", "encryption", "exfil_location", "file", "function", "inject_type", "location", "parameters", "plugin_name", "plugin_type", "recipient_domains", "recipient_file", "redirects", "senders", "service_type", "settings", "target_type", "template", "triggers"]

    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 EventData 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 bot_settings
        if self.bot_settings:
            _dict['bot_settings'] = self.bot_settings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of config_file
        if self.config_file:
            _dict['config_file'] = self.config_file.to_dict()
        # override the default output from pydantic by calling `to_dict()` of controller
        if self.controller:
            _dict['controller'] = self.controller.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in controllers (list)
        _items = []
        if self.controllers:
            for _item_controllers in self.controllers:
                if _item_controllers:
                    _items.append(_item_controllers.to_dict())
            _dict['controllers'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in encryption (list)
        _items = []
        if self.encryption:
            for _item_encryption in self.encryption:
                if _item_encryption:
                    _items.append(_item_encryption.to_dict())
            _dict['encryption'] = _items
        # override the default output from pydantic by calling `to_dict()` of file
        if self.file:
            _dict['file'] = self.file.to_dict()
        # override the default output from pydantic by calling `to_dict()` of location
        if self.location:
            _dict['location'] = self.location.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in recipient_domains (list)
        _items = []
        if self.recipient_domains:
            for _item_recipient_domains in self.recipient_domains:
                if _item_recipient_domains:
                    _items.append(_item_recipient_domains.to_dict())
            _dict['recipient_domains'] = _items
        # override the default output from pydantic by calling `to_dict()` of recipient_file
        if self.recipient_file:
            _dict['recipient_file'] = self.recipient_file.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in redirects (list)
        _items = []
        if self.redirects:
            for _item_redirects in self.redirects:
                if _item_redirects:
                    _items.append(_item_redirects.to_dict())
            _dict['redirects'] = _items
        # override the default output from pydantic by calling `to_dict()` of settings
        if self.settings:
            _dict['settings'] = self.settings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of template
        if self.template:
            _dict['template'] = self.template.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in triggers (list)
        _items = []
        if self.triggers:
            for _item_triggers in self.triggers:
                if _item_triggers:
                    _items.append(_item_triggers.to_dict())
            _dict['triggers'] = _items
        return _dict

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

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

        _obj = cls.model_validate({
            "arguments": obj.get("arguments"),
            "attack_targets": obj.get("attack_targets"),
            "attack_type": obj.get("attack_type"),
            "bot_settings": BotSettings.from_dict(obj["bot_settings"]) if obj.get("bot_settings") is not None else None,
            "command": obj.get("command"),
            "component_type": obj.get("component_type"),
            "config_file": File.from_dict(obj["config_file"]) if obj.get("config_file") is not None else None,
            "controller": EventController.from_dict(obj["controller"]) if obj.get("controller") is not None else None,
            "controllers": [ControllerUrl.from_dict(_item) for _item in obj["controllers"]] if obj.get("controllers") is not None else None,
            "encryption": [Encryption.from_dict(_item) for _item in obj["encryption"]] if obj.get("encryption") is not None else None,
            "exfil_location": obj.get("exfil_location"),
            "file": File.from_dict(obj["file"]) if obj.get("file") is not None else None,
            "function": obj.get("function"),
            "inject_type": obj.get("inject_type"),
            "location": Location.from_dict(obj["location"]) if obj.get("location") is not None else None,
            "parameters": obj.get("parameters"),
            "plugin_name": obj.get("plugin_name"),
            "plugin_type": obj.get("plugin_type"),
            "recipient_domains": [RecipientDomain.from_dict(_item) for _item in obj["recipient_domains"]] if obj.get("recipient_domains") is not None else None,
            "recipient_file": File.from_dict(obj["recipient_file"]) if obj.get("recipient_file") is not None else None,
            "redirects": [Redirect.from_dict(_item) for _item in obj["redirects"]] if obj.get("redirects") is not None else None,
            "senders": obj.get("senders"),
            "service_type": obj.get("service_type"),
            "settings": Settings.from_dict(obj["settings"]) if obj.get("settings") is not None else None,
            "target_type": obj.get("target_type"),
            "template": Template.from_dict(obj["template"]) if obj.get("template") is not None else None,
            "triggers": [Trigger.from_dict(_item) for _item in obj["triggers"]] if obj.get("triggers") is not None else None
        })
        return _obj


