# Copyright (c) 2017, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

# mixbox
from mixbox import fields

# internal
import stix
import stix.bindings.exploit_target as exploit_target_binding
from stix.common.related import (
    GenericRelationshipList, RelatedCOA, RelatedExploitTarget,
    RelatedPackageRefs
)

# relative
from .vulnerability import Vulnerability, _Vulnerabilities  # noqa
from .weakness import Weakness, _Weaknesses  # noqa
from .configuration import Configuration  # noqa
from stix.common import InformationSource

class ExploitTarget(stix.BaseCoreComponent):
    """Implementation of STIX Exploit Target.

    Args:
        id_ (optional): An identifier. If ``None``, a value will be generated
            via ``mixbox.idgen.create_id()``. If set, this will unset the
            ``idref`` property.
        idref (optional): An identifier reference. If set this will unset the
            ``id_`` property.
        title (optional): A string title.
        timestamp (optional): A timestamp value. Can be an instance of
            ``datetime.datetime`` or ``str``.
        description (optional): A string description.
        short_description (optional): A string short description.

    """
    _binding = exploit_target_binding
    _binding_class = _binding.ExploitTargetType
    _namespace = "http://stix.mitre.org/ExploitTarget-1"
    _version = "1.2"
    _ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1", "1.2")
    _ID_PREFIX = 'et'

    potential_coas = fields.TypedField("Potential_COAs", type_="stix.exploit_target.PotentialCOAs")
    related_exploit_targets = fields.TypedField("Related_Exploit_Targets", type_="stix.exploit_target.RelatedExploitTargets")
    vulnerabilities = fields.TypedField("Vulnerability", Vulnerability, multiple=True, key_name="vulnerabilities")
    weaknesses = fields.TypedField("Weakness", Weakness, multiple=True, key_name="weaknesses")
    configuration = fields.TypedField("Configuration", Configuration, multiple=True)
    related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
    information_source = fields.TypedField("Information_Source", InformationSource)

    def __init__(self, id_=None, idref=None, timestamp=None, title=None,
                 description=None, short_description=None):

        super(ExploitTarget, self).__init__(
            id_=id_,
            idref=idref,
            timestamp=timestamp,
            title=title,
            description=description,
            short_description=short_description
        )

        self.potential_coas = PotentialCOAs()
        self.related_exploit_targets = RelatedExploitTargets()
        self.related_packages = RelatedPackageRefs()

    def add_vulnerability(self, value):
        """Adds a vulnerability to the :attr:`vulnerabilities` list property.

        Note:
            If ``None`` is passed in no value is added 

        Args:
            value: A :class:`.Vulnerability` object..
            
        Raises:
            ValueError: if the `value` param is of type :class:`.Vulnerability`

        """
        self.vulnerabilities.append(value)
               
    def add_weakness(self, value):
        """Adds a weakness to the :attr:`weaknesses` list property.

        Note:
            If ``None`` is passed in no value is added 

        Args:
            value: A :class:`.Weakness` object.
            
        Raises: ValueError if the `value` param is of type :class:`.Weakness`

        """
        self.weaknesses.append(value)

    def add_configuration(self, value):
        """Adds a configuration to the :attr:`configurations` list property.

        Note:
            If ``None`` is passed in no value is added 

        Args:
            value: A configuration value.
            
        Raises:
            ValueError: If the `value` param is of type :class:`.Configuration`

        """
        self.configuration.append(value)


class PotentialCOAs(GenericRelationshipList):
    """
    A list of ``Potential_COA`` objects, defaults to empty array
    """
    _namespace = "http://stix.mitre.org/ExploitTarget-1"
    _binding = exploit_target_binding
    _binding_class = exploit_target_binding.PotentialCOAsType

    potential_coa = fields.TypedField("Potential_COA", RelatedCOA, multiple=True, key_name="coas")

    def __init__(self, coas=None, scope=None):
        super(PotentialCOAs, self).__init__(scope, coas)


class RelatedExploitTargets(GenericRelationshipList):
    """
    A list of ``RelatedExploitTargets`` objects, defaults to empty array
    """
    _namespace = "http://stix.mitre.org/ExploitTarget-1"
    _binding = exploit_target_binding
    _binding_class = exploit_target_binding.RelatedExploitTargetsType

    related_exploit_target = fields.TypedField("Related_Exploit_Target", RelatedExploitTarget, multiple=True, key_name="related_exploit_targets")

    def __init__(self, related_exploit_targets=None, scope=None):
        super(RelatedExploitTargets, self).__init__(scope, related_exploit_targets)
