# -*- coding: utf-8 -*-
'''
Botocore waiters for elasticsearch that are not present in boto3+botocore (yet).

:codeauthor: Herbert Buurman <herbert.buurman@ogd.nl>
:depends: boto3
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals

# Import Salt libs
from salt.exceptions import SaltInvocationError
import salt.utils.versions

try:
    import botocore.waiter
except ImportError:
    pass


WAITER_CONFIGS = {
    'ESDomainAvailable': {
        'delay': 60,
        'operation': 'DescribeElasticsearchDomainConfig',
        'maxAttempts': 60,
        'acceptors': [{
            'expected': 'Active',
            'matcher': 'path',
            'state': 'success',
            'argument': 'DomainConfig.ElasticsearchClusterConfig.Status.State',
        }, {
           'expected': True,
           'matcher': 'pathAny',
           'state': 'failure',
           'argument': 'DomainConfig.*.Status.PendingDeletion',
        }],
    },
    'ESUpgradeFinished': {
        'delay': 60,
        'operation': 'DescribeElasticsearchDomain',
        'maxAttempts': 60,
        'acceptors': [{
            'expected': False,
            'matcher': 'path',
            'state': 'success',
            'argument': 'DomainStatus.UpgradeProcessing',
        }],
    },
    'ESDomainDeleted': {
        'delay': 30,
        'operation': 'DescribeElasticsearchDomain',
        'maxAttempts': 60,
        'acceptors': [{
            'expected': True,
            'matcher': 'path',
            'state': 'retry',
            'argument': 'DomainStatus.Deleted',
        }, {
            'expected': False,
            'matcher': 'path',
            'state': 'failure',
            'argument': 'DomainStatus.Processing',
        }, {
            'expected': 'ResourceNotFoundException',
            'matcher': 'error',
            'state': 'success',
        }],
    },
    'ESDomainCreated': {
        'delay': 30,
        'operation': 'DescribeElasticsearchDomain',
        'maxAttempts': 60,
        'acceptors': [{
            'expected': True,
            'matcher': 'path',
            'state': 'success',
            'argument': 'DomainStatus.Created',
        }],
    },
}


def __virtual__():
    '''
    Only load if botocore libraries exist.
    '''
    return salt.utils.versions.check_boto_reqs(check_boto=False)


def get_waiter(client, waiter=None, waiter_config=None):
    '''
    Gets a botocore waiter using either one of the preconfigured models by name
    ``waiter``, or with a manually supplied ``waiter_config``.

    :param botoclient client: The botocore client to use.
    :param str waiter: The name of the waiter config to use.
        Either ``waiter`` or ``waiter_config`` must be supplied.
        If both ``waiter`` and ``waiter_config`` are supplied, ``waiter`` takes
        presedence, unless no configuration for ``waiter`` exists.
    :param dict waiter_config: The manual waiter config to use.
        Either waiter or waiter_config must be supplied.

    :returns botocore.waiter
    '''
    if not any((waiter, waiter_config)):
        raise SaltInvocationError('At least one of waiter or waiter_config must be specified.')
    waiter_model = botocore.waiter.WaiterModel(
        {'version': 2, 'waiters': {waiter: WAITER_CONFIGS.get(waiter, waiter_config)}}
    )
    return botocore.waiter.create_waiter_with_client(waiter, waiter_model, client)


def list_waiters():
    '''
    Lists the builtin waiter configuration names.

    :returns list
    '''
    return WAITER_CONFIGS.keys()
