# 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 logging
import re
import time

from boto.exception import BotoServerError
from unittest2 import TestCase

import tempest.config

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 = 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..
