#!/usr/bin/env python

r"""
Use robot framework API to extract test data from test suites.
Refer to https://robot-framework.readthedocs.io/en/3.0.1/autodoc/robot.parsing.html
"""

import sys
import os
from robot.parsing.model import TestData
sys.path.append(os.path.join(os.path.dirname(__file__), "../lib"))

from gen_arg import *
from gen_print import *
from gen_valid import *

# Set exit_on_error for gen_valid functions.
set_exit_on_error(True)

valid_options = ['name', 'tags', 'doc', 'all']

parser = argparse.ArgumentParser(
    usage='%(prog)s [OPTIONS]',
    description=";%(prog)s will print test suite information to stdout. This \
                  information consists of any and/or all of the following: \
                  the suite name, test case names, tag names and doc strings. \
                  Example for generated test case names \
                  tests/test_basic_poweron.robot \
                  Verify Front And Rear LED At Standby \
                  Power On Test \
                  Check For Application Failures \
                  Verify Uptime Average Against Threshold \
                  Test SSH And IPMI Connections",
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    prefix_chars='-+')

parser.add_argument(
    '--source_path',
    '-s',
    help='The robot test file or directory path.')

parser.add_argument(
    '--option',
    '-o',
    default="name",
    help='Test case attribute name.  This may be any one of the following:\n'
    + sprint_var(valid_options))

# Populate stock_list with options we want.
stock_list = [("test_mode", 0), ("quiet", 0), ("debug", 0)]


def exit_function(signal_number=0,
                  frame=None):
    r"""
    Execute whenever the program ends normally or with the signals that we
    catch (i.e. TERM, INT).
    """

    dprint_executing()

    dprint_var(signal_number)

    qprint_pgm_footer()


def signal_handler(signal_number,
                   frame):
    r"""
    Handle signals.  Without a function to catch a SIGTERM or SIGINT, the
    program would terminate immediately with return code 143 and without
    calling the exit_function.
    """

    # Our convention is to set up exit_function with atexit.register() so
    # there is no need to explicitly call exit_function from here.

    dprint_executing()

    # Calling exit prevents us from returning to the code that was running
    # when the signal was received.
    exit(0)


def validate_parms():
    r"""
    Validate program parameters, etc.  Return True or False (i.e. pass/fail)
    accordingly.
    """

    valid_path(source_path)

    valid_value(option, valid_values=valid_options)

    gen_post_validation(exit_function, signal_handler)


def parse_test_suites(source_path, option):
    r"""
    Parse the robot files and extract test data output.

    Description of argument(s):
    source_path   The path to a robot file or a directory of robot files.
    option        Test case attribute instances such as "name",
                  "tags" or "doc".
    """
    if os.path.isfile(source_path):
        file_paths = [source_path]
    else:
        file_paths = [os.path.join(path, file)
                      for (path, dirs, files) in os.walk(source_path)
                      for file in files]

    for file_path in file_paths:
        print(file_path)
        if "__init__.robot" in file_path:
            continue
        test_suite_obj = TestData(parent=None, source=file_path)
        parse_test_file(test_suite_obj, option)


def parse_test_file(test_suite_obj, option):
    r"""
    Extract test information from test suite object and print it to stdout in
    the following format:

    <Test Case name>
    <Test Tags name>
    <Test Documentation>

    Description of argument(s):
    test_suite_obj    Test data suite object.
    option            Test case attribute instances such as "name",
                      "tags" or "doc".
    """

    for testcase in test_suite_obj.testcase_table:
        if option == "name":
            print(testcase.name)
        elif option == "tags":
            print(testcase.tags)
        elif option == "doc":
            print(testcase.doc)
        elif option == "all":
            print(testcase.name)
            print(testcase.tags)
            print(testcase.doc)


def main():

    gen_get_options(parser, stock_list)

    validate_parms()

    qprint_pgm_header()

    parse_test_suites(source_path, option)

    return True


# Main
main()