#!/usr/bin/env python

r"""
This module provides functions which are useful for running plug-ins.
"""

import sys
import os
import commands
import glob

import gen_print as gp
import gen_misc as gm

# Some help text that is common to more than one program.
plug_in_dir_paths_help_text = \
    'This is a colon-separated list of plug-in directory paths.  If one' +\
    ' of the entries in the list is a plain directory name (i.e. no' +\
    ' path info), it will be taken to be a native plug-in.  In that case,' +\
    ' %(prog)s will search for the native plug-in in the "plug-ins"' +\
    ' subdirectory of each path in the PATH environment variable until it' +\
    ' is found.  Also, integrated plug-ins will automatically be appended' +\
    ' to your plug_in_dir_paths list.  An integrated plug-in is any plug-in' +\
    ' found using the PATH variable that contains a file named "integrated".'

mch_class_help_text = \
    'The class of machine that we are testing (e.g. "op" = "open power",' +\
    ' "obmc" = "open bmc", etc).'

PATH_LIST = gm.return_path_list()


def get_plug_in_base_paths():

    r"""
    Get plug-in base paths and return them as a list.

    This function searches the PATH_LIST (created from PATH environment
    variable) for any paths that have a "plug_ins" subdirectory.  All such
    paths are considered plug_in_base paths.
    """

    global PATH_LIST

    plug_in_base_path_list = []

    for path in PATH_LIST:
        candidate_plug_in_base_path = path + "plug_ins/"
        if os.path.isdir(candidate_plug_in_base_path):
            plug_in_base_path_list.append(candidate_plug_in_base_path)

    return plug_in_base_path_list

# Define global plug_in_base_path_list and call get_plug_in_base_paths to set
# its value.
plug_in_base_path_list = get_plug_in_base_paths()


def find_plug_in_package(plug_in_name):

    r"""
    Find and return the normalized directory path of the specified plug in.
    This is done by searching the global plug_in_base_path_list.

    Description of arguments:
    plug_in_name                    The unqualified name of the plug-in
                                    package.
    """

    global plug_in_base_path_list
    for plug_in_base_dir_path in plug_in_base_path_list:
        candidate_plug_in_dir_path = os.path.normpath(plug_in_base_dir_path +
                                                      plug_in_name) + \
            os.sep
        if os.path.isdir(candidate_plug_in_dir_path):
            return candidate_plug_in_dir_path

    return ""


def validate_plug_in_package(plug_in_dir_path,
                             mch_class="obmc"):

    r"""
    Validate the plug in package and return the normalized plug-in directory
    path.

    Description of arguments:
    plug_in_dir_path                The "relative" or absolute path to a plug
                                    in package directory.
    mch_class                       The class of machine that we are testing
                                    (e.g. "op" = "open power", "obmc" = "open
                                    bmc", etc).
    """

    gp.dprint_executing()

    if os.path.isabs(plug_in_dir_path):
        # plug_in_dir_path begins with a slash so it is an absolute path.
        candidate_plug_in_dir_path = os.path.normpath(plug_in_dir_path) +\
            os.sep
        if not os.path.isdir(candidate_plug_in_dir_path):
            gp.print_error_report("Plug-in directory path \"" +
                                  plug_in_dir_path + "\" does not exist.\n")
            exit(1)
    else:
        # The plug_in_dir_path is actually a simple name (e.g.
        # "OBMC_Sample")...
        candidate_plug_in_dir_path = find_plug_in_package(plug_in_dir_path)
        if candidate_plug_in_dir_path == "":
            global PATH_LIST
            gp.print_error_report("Plug-in directory path \"" +
                                  plug_in_dir_path + "\" could not be found" +
                                  " in any of the following directories:\n" +
                                  gp.sprint_var(PATH_LIST))
            exit(1)
    # Make sure that this plug-in supports us...
    supports_file_path = candidate_plug_in_dir_path + "supports_" + mch_class
    if not os.path.exists(supports_file_path):
        gp.print_error_report("The following file path could not be" +
                              " found:\n" +
                              gp.sprint_varx("supports_file_path",
                                             supports_file_path) +
                              "\nThis file is necessary to indicate that" +
                              " the given plug-in supports the class of" +
                              " machine we are testing, namely \"" +
                              mch_class + "\".\n")
        exit(1)

    return candidate_plug_in_dir_path


def return_integrated_plug_ins(mch_class="obmc"):

    r"""
    Return a list of integrated plug-ins.  Integrated plug-ins are plug-ins
    which are selected without regard for whether the user has specified them.
    In other words, they are "integrated" into the program suite.  The
    programmer designates a plug-in as integrated by putting a file named
    "integrated" into the plug-in package directory.

    Description of arguments:
    mch_class                       The class of machine that we are testing
                                    (e.g. "op" = "open power", "obmc" = "open
                                    bmc", etc).
    """

    global plug_in_base_path_list

    integrated_plug_ins_list = []

    DEBUG_SKIP_INTEGRATED = int(os.getenv('DEBUG_SKIP_INTEGRATED', '0'))

    if DEBUG_SKIP_INTEGRATED:
        return integrated_plug_ins_list

    for plug_in_base_path in plug_in_base_path_list:
        # Get a list of all plug-in paths that support our mch_class.
        mch_class_candidate_list = glob.glob(plug_in_base_path +
                                             "*/supports_" + mch_class)
        for candidate_path in mch_class_candidate_list:
            integrated_plug_in_dir_path = os.path.dirname(candidate_path) +\
                os.sep
            integrated_file_path = integrated_plug_in_dir_path + "integrated"
            if os.path.exists(integrated_file_path):
                plug_in_name = \
                    os.path.basename(os.path.dirname(candidate_path))
                if plug_in_name not in integrated_plug_ins_list:
                    # If this plug-in has not already been added to the list...
                    integrated_plug_ins_list.append(plug_in_name)

    return integrated_plug_ins_list


def return_plug_in_packages_list(plug_in_dir_paths,
                                 mch_class="obmc"):

    r"""
    Return a list of plug-in packages given the plug_in_dir_paths string.
    This function calls validate_plug_in_package so it will fail if
    plug_in_dir_paths contains any invalid plug-ins.

    Description of arguments:
    plug_in_dir_path                The "relative" or absolute path to a plug
                                    in package directory.
    mch_class                       The class of machine that we are testing
                                    (e.g. "op" = "open power", "obmc" = "open
                                    bmc", etc).
    """

    if plug_in_dir_paths != "":
        plug_in_packages_list = plug_in_dir_paths.split(":")
    else:
        plug_in_packages_list = []

    # Get a list of integrated plug-ins (w/o full path names).
    integrated_plug_ins_list = return_integrated_plug_ins(mch_class)
    # Put both lists together in plug_in_packages_list with no duplicates.
    # NOTE: This won't catch duplicates if the caller specifies the full path
    # name of a native plug-in but that should be rare enough.

    plug_in_packages_list = plug_in_packages_list + integrated_plug_ins_list

    plug_in_packages_list = \
        list(set([validate_plug_in_package(path, mch_class)
                  for path in plug_in_packages_list]))

    return plug_in_packages_list
