# Copyright (C) 2018 The Android Open Source Project
#
# 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 random
import string
import time

from kubernetes import client


class TimeOutException(Exception):
    """Exception to be raised, if some action does not finish in time."""


def exec_fn_with_timeout(func, limit=60):
    """Helper function that executes a given function until it returns True or a
       given time limit is reached.

    Arguments:
      func {function} -- Function to execute. The function can return some output
                      (or None) and as a second return value a boolean indicating,
                      whether the event the function was waiting for has happened.

    Keyword Arguments:
      limit {int} -- Maximum time in seconds to wait for a positive response of
                     the function (default: {60})

    Returns:
      boolean -- False, if the timeout was reached
      any -- Last output of fn
    """

    timeout = time.time() + limit
    while time.time() < timeout:
        is_finished = func()
        if is_finished:
            return True
    return False


def wait_for_pod_readiness(pod_labels, timeout=180):
    """Helper function that can be used to wait for all pods with a given set of
       labels to be ready.

    Arguments:
      pod_labels {str} -- Label selector string to be used to select pods.
        (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors)

    Keyword Arguments:
      timeout {int} -- Time in seconds to wait for the pod status to become ready.
        (default: {180})

    Returns:
      boolean -- Whether pods were ready in time.
    """

    def check_pod_readiness():
        core_v1 = client.CoreV1Api()
        pod_list = core_v1.list_pod_for_all_namespaces(
            watch=False, label_selector=pod_labels
        )
        for pod in pod_list.items:
            for condition in pod.status.conditions:
                if condition.type != "Ready" and condition.status != "True":
                    return False
        return True

    return exec_fn_with_timeout(check_pod_readiness, limit=timeout)


def check_if_ancestor_image_is_inherited(image, ancestor):
    """Helper function that looks for a given ancestor image in the layers of a
      provided image. It can be used to check, whether an image uses the expected
      FROM-statement

    Arguments:
      image {docker.images.Image} -- Docker image object to be checked
      ancestor {str} -- Complete name of the expected ancestor image

    Returns:
      boolean -- True, if ancestor is inherited by image
    """

    contains_tag = False
    for layer in image.history():
        contains_tag = layer["Tags"] is not None and ancestor in layer["Tags"]
        if contains_tag:
            break
    return contains_tag


def create_random_string(length=8):
    return "".join([random.choice(string.ascii_letters) for n in range(length)]).lower()
