# Copyright 1999-2014. Parallels IP Holdings GmbH. All Rights Reserved.
""" Helpers for batch operations on mails rate limiting DB objects. """
from plesk_outgoing_mail_db import OutgoingMailLimitsDb

class OutgoingMailBatchOperationsHelper(object):
    """ Helper class to create multiple outgoing mails rate limiting DB objects and/or set their limits based on a
        supplied dictionary.
    """
    def __init__(self, db):
        self._db = db

    def _get_main_domain_name(self, subscr):
        """ Returns mail domain name for a given subscription dictionary.
            
            >>> h._get_main_domain_name(subscription_full)
            'main-domain.tld'
        """
        main_domains = filter(lambda x: x["is_main"], subscr["domains"])
        if len(main_domains) != 1:
            raise Exception("Incorrect number of main domains in subscription (expected 1): %s" % (main_domains,))
        return main_domains[0]["name"]

    def set_subscription_limits(self, subscr):
        """ Set limits for subscription and its child objects based on supplied dictionary. """
        main_domain_name = self._get_main_domain_name(subscr)
        self._db.set_subscription_limits(main_domain_name, subscr.get("out_limit"), subscr.get("allow_sendmail"))
        for domain in subscr.get("domains", []):
            domain_name = domain["name"]
            self._db.set_domain_limits(domain_name, domain.get("out_limit"))
            for mail in domain.get("mails", []):
                mail_name = mail["name"]
                self._db.set_mailname_limits(mail_name, domain_name, mail.get("out_limit"))

    def create_subscription_entries(self, subscr):
        """ Create subscription and its child objects based on supplied dictionary.
            
            >>> h.create_subscription_entries(subscription_full)
            >>> skip_keys(db.fetch_subscription('main-domain.tld'), '_id') == {
            ...         'main_domain_name': 'main-domain.tld', 
            ...         'out_limit': -1, 'allow_sendmail': 1}
            True
            >>> h.set_subscription_limits(subscription_full)
            >>> skip_keys(db.fetch_subscription('main-domain.tld'), '_id') == {
            ...         'main_domain_name': 'main-domain.tld', 
            ...         'out_limit': 100, 'allow_sendmail': 0}
            True
            >>> skip_keys(db.fetch_sysuser('root'), '_id', 'out_limit', 'allow_sendmail') == {
            ...         'sysuser_uid': 0,
            ...         'sysuser_name': 'root',
            ...         'main_domain_name': 'main-domain.tld'}
            True
            >>> skip_keys(db.fetch_domain_by_alias('alias-addon-domain.tld'), '_id') == {
            ...         'name': 'addon-domain.tld',
            ...         'main_domain_name': 'main-domain.tld',
            ...         'out_limit': 11}
            True
            >>> skip_keys(db.fetch_domain_by_vhost_id('e0b0b52c-cf6e-4c72-bc21-5573bb83fafe'), '_id') == {
            ...         'name': 'main-domain.tld',
            ...         'main_domain_name': 'main-domain.tld',
            ...         'out_limit': 10}
            True
            >>> skip_keys(db.fetch_mailname_by_aliases('alias-mail', 'alias-addon-domain.tld'), '_id') == {
            ...         'mail_name': 'mail', 
            ...         'domain_name': 'addon-domain.tld', 
            ...         'out_limit': 1}
            True
        """
        main_domain_name = self._get_main_domain_name(subscr).lower()
        self._db.create_subscription(main_domain_name)

        for sysuser_name in subscr.get("sysusers", []):
            self._db.create_sysuser(sysuser_name, main_domain_name)

        for domain in subscr["domains"]:
            domain_name = domain["name"].lower()
            if not domain["is_main"]:
                self._db.create_domain(domain_name, main_domain_name)

            self._db.add_vhost_id(domain["vhost_id"], domain_name)

            for alias in domain["aliases"]:
                self._db.create_domain_alias(alias.lower(), domain_name)

            for mail in domain["mails"]:
                mail_name = mail["name"].lower()
                self._db.create_mailname(mail_name, domain_name)

                for alias in mail["aliases"]:
                    self._db.create_mailname_alias(alias.lower(), mail_name, domain_name)

if __name__ == '__main__':
    import doctest
    import sys

    def skip_keys(dictionary, *keys):
        for key in keys:
            dictionary.pop(key, None)
        return dictionary

    db = OutgoingMailLimitsDb(OutgoingMailLimitsDb.IN_MEMORY)
    h = OutgoingMailBatchOperationsHelper(db)
    subscription_full = {
        'sysusers': ['root'],
        'out_limit': 100,
        'allow_sendmail': False,
        'domains': [{
            'name': 'main-domain.tld',
            'is_main': True,
            'out_limit': 10,
            'vhost_id': 'e0b0b52c-cf6e-4c72-bc21-5573bb83fafe',
            'aliases': [],
            'mails': [{
                'name': 'mail',
                'out_limit': 1,
                'aliases': []
            }]
        }, {
            'name': 'addon-domain.tld',
            'is_main': False,
            'out_limit': 11,
            'vhost_id': '00000000-0000-0000-0000-000000000000',
            'aliases': ['alias-addon-domain.tld'],
            'mails': [{
                'name': 'mail',
                'out_limit': 1,
                'aliases': ['alias-mail']
            }]
        }]
    }

    sys.exit( doctest.testmod().failed )

# vim: ts=4 sts=4 sw=4 et :
