# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 OpenStack, LLC
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import re
import time

import boto.exception
from testtools import TestCase

import tempest.config
from tempest.openstack.common import log as logging

LOG = logging.getLogger(__name__)

_boto_config = tempest.config.TempestConfig().boto

default_timeout = _boto_config.build_timeout

default_check_interval = _boto_config.build_interval


def state_wait(lfunction, final_set=set(), valid_set=None):
    # TODO(afazekas): evaluate using ABC here
    if not isinstance(final_set, set):
        final_set = set((final_set,))
    if not isinstance(valid_set, set) and valid_set is not None:
        valid_set = set((valid_set,))
    start_time = time.time()
    old_status = status = lfunction()
    while True:
        if status != old_status:
            LOG.info('State transition "%s" ==> "%s" %d second', old_status,
                     status, time.time() - start_time)
        if status in final_set:
            return status
        if valid_set is not None and status not in valid_set:
            return status
        dtime = time.time() - start_time
        if dtime > default_timeout:
            raise TestCase.failureException("State change timeout exceeded!"
                                            '(%ds) While waiting'
                                            'for %s at "%s"' %
                                            (dtime,
                                            final_set, status))
        time.sleep(default_check_interval)
        old_status = status
        status = lfunction()


def re_search_wait(lfunction, regexp):
    """Stops waiting on success."""
    start_time = time.time()
    while True:
        text = lfunction()
        result = re.search(regexp, text)
        if result is not None:
            LOG.info('Pattern "%s" found in %d second in "%s"',
                     regexp,
                     time.time() - start_time,
                     text)
            return result
        dtime = time.time() - start_time
        if dtime > default_timeout:
            raise TestCase.failureException('Pattern find timeout exceeded!'
                                            '(%ds) While waiting for'
                                            '"%s" pattern in "%s"' %
                                            (dtime,
                                            regexp, text))
        time.sleep(default_check_interval)


def wait_no_exception(lfunction, exc_class=None, exc_matcher=None):
    """Stops waiting on success."""
    start_time = time.time()
    if exc_matcher is not None:
        exc_class = boto.exception.BotoServerError

    if exc_class is None:
        exc_class = BaseException
    while True:
        result = None
        try:
            result = lfunction()
            LOG.info('No Exception in %d second',
                     time.time() - start_time)
            return result
        except exc_class as exc:
            if exc_matcher is not None:
                res = exc_matcher.match(exc)
                if res is not None:
                    LOG.info(res)
                    raise exc
        # Let the other exceptions propagate
        dtime = time.time() - start_time
        if dtime > default_timeout:
            raise TestCase.failureException("Wait timeout exceeded! (%ds)" %
                                            dtime)
        time.sleep(default_check_interval)


# NOTE(afazekas): EC2/boto normally raise exception instead of empty list
def wait_exception(lfunction):
    """Returns with the exception or raises one."""
    start_time = time.time()
    while True:
        try:
            lfunction()
        except BaseException as exc:
            LOG.info('Exception in %d second',
                     time.time() - start_time)
            return exc
        dtime = time.time() - start_time
        if dtime > default_timeout:
            raise TestCase.failureException("Wait timeout exceeded! (%ds)" %
                                            dtime)
        time.sleep(default_check_interval)

# TODO(afazekas): consider strategy design pattern..
