#!/usr/bin/env python

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

import sys
import os
try:
    import commands
except ImportError:
    import subprocess

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
