#!/usr/bin/env python

r"""
This module has functions to support various data structures such as the
boot_table, valid_boot_list and boot_results_table.
"""

import os
import tempfile
import json
import glob
from tally_sheet import *

from robot.libraries.BuiltIn import BuiltIn
try:
    from robot.utils import DotDict
except ImportError:
    import collections

import gen_print as gp
import gen_valid as gv
import gen_misc as gm
import gen_cmd as gc
import var_funcs as vf

# The code base directory will be one level up from the directory containing
# this module.
code_base_dir_path = os.path.dirname(os.path.dirname(__file__)) + os.sep


def create_boot_table(file_path=None,
                      os_host=""):
    r"""
    Read the boot table JSON file, convert it to an object and return it.

    Note that if the user is running without a global OS_HOST robot variable
    specified, this function will remove all of the "os_" start and end state
    requirements from the JSON data.

    Description of argument(s):
    file_path                       The path to the boot_table file.  If this
                                    value is not specified, it will be
                                    obtained from the "BOOT_TABLE_PATH"
                                    environment variable, if set.  Otherwise,
                                    it will default to "data/boot_table.json".
                                    If this value is a relative path, this
                                    function will use the code_base_dir_path
                                    as the base directory (see definition
                                    above).
    os_host                         The host name or IP address of the host
                                    associated with the machine being tested.
                                    If the user is running without an OS_HOST
                                    (i.e. if this argument is blank), we
                                    remove os starting and ending state
                                    requirements from the boot entries.
    """
    if file_path is None:
        file_path = os.environ.get('BOOT_TABLE_PATH', 'data/boot_table.json')

    if not file_path.startswith("/"):
        file_path = code_base_dir_path + file_path

    # Pre-process the file by removing blank lines and comment lines.
    temp = tempfile.NamedTemporaryFile()
    temp_file_path = temp.name

    cmd_buf = "egrep -v '^[ ]*$|^[ ]*#' " + file_path + " > " + temp_file_path
    gc.cmd_fnc_u(cmd_buf, quiet=1)

    boot_file = open(temp_file_path)
    boot_table = json.load(boot_file, object_hook=DotDict)

    # If the user is running without an OS_HOST, we remove os starting and
    # ending state requirements from the boot entries.
    if os_host == "":
        for boot in boot_table:
            state_keys = ['start', 'end']
            for state_key in state_keys:
                for sub_state in list(boot_table[boot][state_key]):
                    if sub_state.startswith("os_"):
                        boot_table[boot][state_key].pop(sub_state, None)

    # For every boot_type we should have a corresponding mfg mode boot type.
    enhanced_boot_table = DotDict()
    for key, value in boot_table.items():
        enhanced_boot_table[key] = value
        enhanced_boot_table[key + " (mfg)"] = value

    return enhanced_boot_table


def create_valid_boot_list(boot_table):
    r"""
    Return a list of all of the valid boot types (e.g. ['REST Power On', 'REST
    Power Off', ...]).

    Description of argument(s):
    boot_table                      A boot table such as is returned by the
                                    create_boot_table function.
    """

    return list(boot_table.keys())


def read_boot_lists(dir_path="data/boot_lists/"):
    r"""
    Read the contents of all the boot lists files found in the given boot
    lists directory and return dictionary of the lists.

    Boot lists are simply files containing a boot test name on each line.
    These files are useful for categorizing and organizing boot tests.  For
    example, there may be a "Power_on" list, a "Power_off" list, etc.

    The names of the boot list files will be the keys to the top level
    dictionary.  Each dictionary entry is a list of all the boot tests found
    in the corresponding file.

    Here is an abbreviated look at the resulting boot_lists dictionary.

    boot_lists:
      boot_lists[All]:
        boot_lists[All][0]:                           REST Power On
        boot_lists[All][1]:                           REST Power Off
    ...
      boot_lists[Code_update]:
        boot_lists[Code_update][0]:                   BMC oob hpm
        boot_lists[Code_update][1]:                   BMC ib hpm
    ...

    Description of argument(s):
    dir_path                        The path to the directory containing the
                                    boot list files.  If this value is a
                                    relative path, this function will use the
                                    code_base_dir_path as the base directory
                                    (see definition above).
    """

    if not dir_path.startswith("/"):
        # Dir path is relative.
        dir_path = code_base_dir_path + dir_path

    # Get a list of all file names in the directory.
    boot_file_names = os.listdir(dir_path)

    boot_lists = DotDict()
    for boot_category in boot_file_names:
        file_path = gm.which(dir_path + boot_category)
        boot_list = gm.file_to_list(file_path, newlines=0, comments=0, trim=1)
        boot_lists[boot_category] = boot_list

    return boot_lists


def valid_boot_list(boot_list,
                    valid_boot_types):
    r"""
    Verify that each entry in boot_list is a supported boot test.

    Description of argument(s):
    boot_list                       An array (i.e. list) of boot test types
                                    (e.g. "REST Power On").
    valid_boot_types                A list of valid boot types such as that
                                    returned by create_valid_boot_list.
    """

    for boot_name in boot_list:
        boot_name = boot_name.strip(" ")
        error_message = gv.valid_value(boot_name,
                                       valid_values=valid_boot_types,
                                       var_name="boot_name")
        if error_message != "":
            BuiltIn().fail(gp.sprint_error(error_message))


class boot_results:

    r"""
    This class defines a boot_results table.
    """

    def __init__(self,
                 boot_table,
                 boot_pass=0,
                 boot_fail=0,
                 obj_name='boot_results'):
        r"""
        Initialize the boot results object.

        Description of argument(s):
        boot_table                  Boot table object (see definition above).
                                    The boot table contains all of the valid
                                    boot test types.  It can be created with
                                    the create_boot_table function.
        boot_pass                   An initial boot_pass value.  This program
                                    may be called as part of a larger test
                                    suite.  As such there may already have
                                    been some successful boot tests that we
                                    need to keep track of.
        boot_fail                   An initial boot_fail value.  This program
                                    may be called as part of a larger test
                                    suite.  As such there may already have
                                    been some unsuccessful boot tests that we
                                    need to keep track of.
        obj_name                    The name of this object.
        """

        # Store the method parms as class data.
        self.__obj_name = obj_name
        self.__initial_boot_pass = boot_pass
        self.__initial_boot_fail = boot_fail

        # Create boot_results_fields for use in creating boot_results table.
        boot_results_fields = DotDict([('total', 0), ('pass', 0), ('fail', 0)])
        # Create boot_results table.
        self.__boot_results = tally_sheet('boot type',
                                          boot_results_fields,
                                          'boot_test_results')
        self.__boot_results.set_sum_fields(['total', 'pass', 'fail'])
        self.__boot_results.set_calc_fields(['total=pass+fail'])
        # Create one row in the result table for each kind of boot test in
        # the boot_table (i.e. for all supported boot tests).
        for boot_name in list(boot_table.keys()):
            self.__boot_results.add_row(boot_name)

    def add_row(self, *args, **kwargs):
        r"""
        Add row to tally_sheet class object.

        Description of argument(s):
        See add_row method in tally_sheet.py for a description of all
        arguments.
        """
        self.__boot_results.add_row(*args, **kwargs)

    def return_total_pass_fail(self):
        r"""
        Return the total boot_pass and boot_fail values.  This information is
        comprised of the pass/fail values from the table plus the initial
        pass/fail values.
        """

        totals_line = self.__boot_results.calc()
        return totals_line['pass'] + self.__initial_boot_pass,\
            totals_line['fail'] + self.__initial_boot_fail

    def update(self,
               boot_type,
               boot_status):
        r"""
        Update our boot_results_table.  This includes:
        - Updating the record for the given boot_type by incrementing the pass
          or fail field.
        - Calling the calc method to have the totals calculated.

        Description of argument(s):
        boot_type                   The type of boot test just done (e.g.
                                    "REST Power On").
        boot_status                 The status of the boot just done.  This
                                    should be equal to either "pass" or "fail"
                                    (case-insensitive).
        """

        self.__boot_results.inc_row_field(boot_type, boot_status.lower())
        self.__boot_results.calc()

    def sprint_report(self,
                      header_footer="\n"):
        r"""
        String-print the formatted boot_resuls_table and return them.

        Description of argument(s):
        header_footer               This indicates whether a header and footer
                                    are to be included in the report.
        """

        buffer = ""

        buffer += gp.sprint(header_footer)
        buffer += self.__boot_results.sprint_report()
        buffer += gp.sprint(header_footer)

        return buffer

    def print_report(self,
                     header_footer="\n",
                     quiet=None):
        r"""
        Print the formatted boot_resuls_table to the console.

        Description of argument(s):
        See sprint_report for details.
        quiet                       Only print if this value is 0.  This
                                    function will search upward in the stack
                                    to get the default value.
        """

        quiet = int(gm.dft(quiet, gp.get_stack_var('quiet', 0)))

        gp.qprint(self.sprint_report(header_footer))

    def sprint_obj(self):
        r"""
        sprint the fields of this object.  This would normally be for debug
        purposes only.
        """

        buffer = ""

        buffer += "class name: " + self.__class__.__name__ + "\n"
        buffer += gp.sprint_var(self.__obj_name)
        buffer += self.__boot_results.sprint_obj()
        buffer += gp.sprint_var(self.__initial_boot_pass)
        buffer += gp.sprint_var(self.__initial_boot_fail)

        return buffer

    def print_obj(self):
        r"""
        Print the fields of this object to stdout.  This would normally be for
        debug purposes.
        """

        gp.gp_print(self.sprint_obj())


def create_boot_results_file_path(pgm_name,
                                  openbmc_nickname,
                                  master_pid):
    r"""
    Create a file path to be used to store a boot_results object.

    Description of argument(s):
    pgm_name                        The name of the program.  This will form
                                    part of the resulting file name.
    openbmc_nickname                The name of the system.  This could be a
                                    nickname, a hostname, an IP, etc.  This
                                    will form part of the resulting file name.
    master_pid                      The master process id which will form part
                                    of the file name.
   """

    USER = os.environ.get("USER", "")
    dir_path = "/tmp/" + USER + "/"
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)

    file_name_dict = vf.create_var_dict(pgm_name, openbmc_nickname, master_pid)
    return vf.create_file_path(file_name_dict, dir_path=dir_path,
                               file_suffix=":boot_results")


def cleanup_boot_results_file():
    r"""
    Delete all boot results files whose corresponding pids are no longer
    active.
    """

    # Use create_boot_results_file_path to create a globex to find all of the
    # existing boot results files.
    globex = create_boot_results_file_path("*", "*", "*")
    file_list = sorted(glob.glob(globex))
    for file_path in file_list:
        # Use parse_file_path to extract info from the file path.
        file_dict = vf.parse_file_path(file_path)
        if gm.pid_active(file_dict['master_pid']):
            gp.qprint_timen("Preserving " + file_path + ".")
        else:
            gc.cmd_fnc("rm -f " + file_path)


def update_boot_history(boot_history, boot_start_message, max_boot_history=10):
    r"""
    Update the boot_history list by appending the boot_start_message and by
    removing all but the last n entries.

    Description of argument(s):
    boot_history                    A list of boot start messages.
    boot_start_message              This is typically a time-stamped line of
                                    text announcing the start of a boot test.
    max_boot_history                The max number of entries to be kept in
                                    the boot_history list.  The oldest entries
                                    are deleted to achieve this list size.
    """

    boot_history.append(boot_start_message)

    # Trim list to max number of entries.
    del boot_history[:max(0, len(boot_history) - max_boot_history)]


def print_boot_history(boot_history, quiet=None):
    r"""
    Print the last ten boots done with their time stamps.

    Description of argument(s):
    quiet                           Only print if this value is 0.  This
                                    function will search upward in the stack
                                    to get the default value.
    """

    quiet = int(gm.dft(quiet, gp.get_stack_var('quiet', 0)))

    # indent 0, 90 chars wide, linefeed, char is "="
    gp.qprint_dashes(0, 90)
    gp.qprintn("Last 10 boots:\n")

    for boot_entry in boot_history:
        gp.qprint(boot_entry)
    gp.qprint_dashes(0, 90)
