from parallels.plesk.hosting_description.validate.validators.base import ValidatorBase
from parallels.plesk import messages


class ValidatorDict(ValidatorBase):
    """Check that specified document is a dictionary, that conforms specified restrictions for items
        * list of possible keys is not restricted
        * all values have the same type
    """

    def __init__(self, key_item, value_item):
        """
        :type key_item: parallels.plesk.hosting_description.validate.validators.base.ValidatorBase
        :type value_item: parallels.plesk.hosting_description.validate.validators.base.ValidatorBase
        """
        self._key_item = key_item
        self._value_item = value_item

    def validate(self, document, context=None):
        """Validate specified document (variable) according to current validator's rules

        Return list of found issues.

        :rtype: list[unicode]
        """
        if not self.match_type(document):
            return [self._format_error(messages.VALIDATOR_EXPECTED_DICT_VALUE, context)]

        errors = []
        for key, value in document.items():
            errors += self._key_item.validate(key, context)
            errors += self._value_item.validate(value, context)
        return errors

    def match_type(self, document):
        """Check whether data type of document matched the validator

        That is necessary condition for "validate" method not to return errors

        :rtype: bool
        """
        return isinstance(document, dict)

    @property
    def key_item(self):
        """
        :rtype: parallels.plesk.hosting_description.validate.validators.base.ValidatorBase
        """
        return self._key_item

    @property
    def value_item(self):
        """
        :rtype: parallels.plesk.hosting_description.validate.validators.base.ValidatorBase
        """
        return self._value_item

    def __repr__(self):
        return 'ValidatorDict(%r, %r)' % (self._key_item, self._value_item)

    def __eq__(self, other):
        return (
            isinstance(other, ValidatorDict) and
            other.key_item == self.key_item and
            other.value_item == self.value_item
        )
