#!/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
