#!/usr/bin/env python

r"""
This module provides utilities for code updates.
"""

import os
import re
import sys
import tarfile
import time
import collections
from robot.libraries.BuiltIn import BuiltIn

robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
repo_data_path = re.sub('/lib', '/data', robot_pgm_dir_path)
sys.path.append(repo_data_path)

import bmc_ssh_utils as bsu
import gen_robot_keyword as keyword
import gen_print as gp
import variables as var
from robot.libraries.BuiltIn import BuiltIn


def get_bmc_firmware(image_type, sw_dict):
    r"""
    Get the dictionary of image based on image type like either BMC or Host.

    Description of argument(s):
    image_type                     This value is either BMC update or Host update type.
    sw_dict                        This contain dictionary of firmware inventory properties.
    """

    temp_dict = collections.OrderedDict()
    for key, value in sw_dict.items():
        if value['image_type'] == image_type:
            temp_dict[key] = value
        else:
            pass
    return temp_dict


def verify_no_duplicate_image_priorities(image_purpose):
    r"""
    Check that there are no active images with the same purpose and priority.

    Description of argument(s):
    image_purpose                   The purpose that images must have to be
                                    checked for priority duplicates.
    """

    taken_priorities = {}
    _, image_names = keyword.run_key("Get Software Objects  "
                                     + "version_type=" + image_purpose)

    for image_name in image_names:
        _, image = keyword.run_key("Get Host Software Property  " + image_name)
        if image["Activation"] != var.ACTIVE:
            continue
        image_priority = image["Priority"]
        if image_priority in taken_priorities:
            BuiltIn().fail("Found active images with the same priority.\n"
                           + gp.sprint_vars(image,
                                            taken_priorities[image_priority]))
        taken_priorities[image_priority] = image


def get_non_running_bmc_software_object():
    r"""
    Get the URI to a BMC image from software that is not running on the BMC.
    """

    # Get the version of the image currently running on the BMC.
    _, cur_img_version = keyword.run_key("Get BMC Version")
    # Remove the surrounding double quotes from the version.
    cur_img_version = cur_img_version.replace('"', '')

    _, images = keyword.run_key("Read Properties  "
                                + var.SOFTWARE_VERSION_URI + "enumerate")

    for image_name in images:
        _, image_properties = keyword.run_key(
            "Get Host Software Property  " + image_name)
        if 'Purpose' in image_properties and 'Version' in image_properties \
                and image_properties['Purpose'] != var.VERSION_PURPOSE_HOST \
                and image_properties['Version'] != cur_img_version:
            return image_name
    BuiltIn().fail("Did not find any non-running BMC images.")


def delete_all_pnor_images():
    r"""
    Delete all PNOR images from the BMC.
    """

    keyword.run_key("Initiate Host PowerOff")

    status, images = keyword.run_key("Get Software Objects  "
                                     + var.VERSION_PURPOSE_HOST)
    for image_name in images:
        keyword.run_key("Delete Image And Verify  " + image_name + "  "
                        + var.VERSION_PURPOSE_HOST)


def wait_for_activation_state_change(version_id, initial_state):
    r"""
    Wait for the current activation state of ${version_id} to
    change from the state provided by the calling function.

    Description of argument(s):
    version_id                      The version ID whose state change we are
                                    waiting for.
    initial_state                   The activation state we want to wait for.
    """

    keyword.run_key_u("Open Connection And Log In")
    retry = 0
    num_read_errors = 0
    read_fail_threshold = 1
    while (retry < 60):
        status, software_state = keyword.run_key("Read Properties  "
                                                 + var.SOFTWARE_VERSION_URI
                                                 + str(version_id),
                                                 ignore=1)
        if status == 'FAIL':
            num_read_errors += 1
            if num_read_errors > read_fail_threshold:
                message = "Read errors exceeds threshold:\n " \
                    + gp.sprint_vars(num_read_errors, read_fail_threshold)
                BuiltIn().fail(message)
            time.sleep(10)
            continue

        current_state = (software_state)["Activation"]
        if (initial_state == current_state):
            time.sleep(10)
            retry += 1
            num_read_errors = 0
        else:
            return
    return


def get_latest_file(dir_path):
    r"""
    Get the path to the latest uploaded file.

    Description of argument(s):
    dir_path                        Path to the dir from which the name of the
                                    last updated file or folder will be
                                    returned to the calling function.
    """

    stdout, stderr, rc = \
        bsu.bmc_execute_command("cd " + dir_path
                                + "; stat -c '%Y %n' * |"
                                + " sort -k1,1nr | head -n 1")
    return stdout.split(" ")[-1]


def get_version_tar(tar_file_path):
    r"""
    Read the image version from the MANIFEST inside the tarball.

    Description of argument(s):
    tar_file_path                   The path to a tar file that holds the image
                                    version inside the MANIFEST.
    """

    version = ""
    tar = tarfile.open(tar_file_path)
    for member in tar.getmembers():
        BuiltIn().log_to_console(member.name)
        if member.name != "MANIFEST":
            continue
        f = tar.extractfile(member)
        content = f.read()
        if content.find(b"version=") == -1:
            # This tar member does not contain the version.
            continue
        content = content.decode("utf-8", "ignore").split("\n")
        content = [x for x in content if "version=" in x]
        version = content[0].split("=")[-1]
        break
    tar.close()
    return version


def get_image_version(file_path):
    r"""
    Read the file for a version object.

    Description of argument(s):
    file_path                       The path to a file that holds the image
                                    version.
    """

    stdout, stderr, rc = \
        bsu.bmc_execute_command("cat " + file_path
                                + " | grep \"version=\"", ignore_err=1)
    return (stdout.split("\n")[0]).split("=")[-1]


def get_image_purpose(file_path):
    r"""
    Read the file for a purpose object.

    Description of argument(s):
    file_path                       The path to a file that holds the image
                                    purpose.
    """

    stdout, stderr, rc = \
        bsu.bmc_execute_command("cat " + file_path
                                + " | grep \"purpose=\"", ignore_err=1)
    return stdout.split("=")[-1]


def get_image_path(image_version):
    r"""
    Query the upload image dir for the presence of image matching
    the version that was read from the MANIFEST before uploading
    the image. Based on the purpose verify the activation object
    exists and is either READY or INVALID.

    Description of argument(s):
    image_version                   The version of the image that should match
                                    one of the images in the upload dir.
    """

    stdout, stderr, rc = \
        bsu.bmc_execute_command("ls -d " + var.IMAGE_UPLOAD_DIR_PATH + "*/")

    image_list = stdout.split("\n")
    retry = 0
    while (retry < 10):
        for i in range(0, len(image_list)):
            version = get_image_version(image_list[i] + "MANIFEST")
            if (version == image_version):
                return image_list[i]
        time.sleep(10)
        retry += 1


def verify_image_upload(image_version,
                        timeout=3):
    r"""
    Verify the image was uploaded correctly and that it created
    a valid d-bus object. If the first check for the image
    fails, try again until we reach the timeout.

    Description of argument(s):
    image_version                   The version from the image's manifest file
                                    (e.g. "v2.2-253-g00050f1").
    timeout                         How long, in minutes, to keep trying to
                                    find the image on the BMC. Default is 3 minutes.
    """

    image_path = get_image_path(image_version)
    image_version_id = image_path.split("/")[-2]

    keyword.run_key_u("Open Connection And Log In")
    image_purpose = get_image_purpose(image_path + "MANIFEST")
    if (image_purpose == var.VERSION_PURPOSE_BMC
            or image_purpose == var.VERSION_PURPOSE_HOST):
        uri = var.SOFTWARE_VERSION_URI + image_version_id
        ret_values = ""
        for itr in range(timeout * 2):
            status, ret_values = \
                keyword.run_key("Read Attribute  " + uri + "  Activation")

            if ((ret_values == var.READY) or (ret_values == var.INVALID)
                    or (ret_values == var.ACTIVE)):
                return True, image_version_id
            else:
                time.sleep(30)

        # If we exit the for loop, the timeout has been reached
        gp.print_var(ret_values)
        return False, None
    else:
        gp.print_var(image_purpose)
        return False, None


def verify_image_not_in_bmc_uploads_dir(image_version, timeout=3):
    r"""
    Check that an image with the given version is not unpacked inside of the
    BMCs image uploads directory. If no image is found, retry every 30 seconds
    until the given timeout is hit, in case the BMC takes time
    unpacking the image.

    Description of argument(s):
    image_version                   The version of the image to look for on
                                    the BMC.
    timeout                         How long, in minutes, to try to find an
                                    image on the BMC. Default is 3 minutes.
    """

    for i in range(timeout * 2):
        stdout, stderr, rc = \
            bsu.bmc_execute_command('ls ' + var.IMAGE_UPLOAD_DIR_PATH
                                    + '*/MANIFEST 2>/dev/null '
                                    + '| xargs grep -rl "version='
                                    + image_version + '"')
        image_dir = os.path.dirname(stdout.split('\n')[0])
        if '' != image_dir:
            bsu.bmc_execute_command('rm -rf ' + image_dir)
            BuiltIn().fail('Found invalid BMC Image: ' + image_dir)
        time.sleep(30)
