#!/usr/bin/env python

r"""
See redfish_plus class prolog below for details.
"""

from redfish.rest.v1 import HttpClient
import gen_print as gp
import func_args as fa


def valid_http_status_code(status, valid_status_codes):
    r"""
    Raise exception if status is not found in the valid_status_codes list.

    Description of argument(s):
    status                          An HTTP status code (e.g. 200, 400, etc.).
    valid_status_codes              A list of status codes that the caller
                                    considers acceptable.  If this is a null
                                    list, then any status code is considered
                                    acceptable.  Note that for the convenience
                                    of the caller, valid_status_codes may be
                                    either a python list or a string which can
                                    be evaluated to become a python list (e.g.
                                    "[200]").
    """

    if type(valid_status_codes) is not list:
        valid_status_codes = eval(valid_status_codes)
    if len(valid_status_codes) == 0:
        return
    if status in valid_status_codes:
        return

    message = "The HTTP status code was not valid:\n"
    message += gp.sprint_vars(status, valid_status_codes)
    raise ValueError(message)


class redfish_plus(HttpClient):
    r"""
    redfish_plus is a wrapper for redfish rest that provides the following
    benefits vs. using redfish directly:

    For rest_request functions (e.g. get, put, post, etc.):
        - Function-call logging to stdout.
        - Automatic valid_status_codes processing (i.e. an exception will be
          raised if the rest response status code is not as expected.
        - Easily used from robot programs.
    """

    ROBOT_LIBRARY_SCOPE = 'TEST SUITE'

    def rest_request(self, func, *args, **kwargs):
        r"""
        Perform redfish rest request and return response.

        This function provides the following additional functionality.
        - The calling function's call line is logged to standard out (provided
          that global variable "quiet" is not set).
        - The caller may include a valid_status_codes argument.
        - Callers may include inline python code strings to define arguments.
          This predominantly benefits robot callers.

          For example, instead of calling like this:
            ${data}=  Create Dictionary  HostName=${hostname}
            Redfish.patch  ${REDFISH_NW_PROTOCOL_URI}  body=&{data}

          Callers may do this:

            Redfish.patch  ${REDFISH_NW_PROTOCOL_URI}
            ...  body=[('HostName', '${hostname}')]

        Description of argument(s):
        func                        A reference to the parent class function
                                    which is to be called (e.g. get, put,
                                    etc.).
        args                        This is passed directly to the function
                                    referenced by the func argument (see the
                                    documentation for the corresponding
                                    redfish HttpClient method for details).
        kwargs                      This is passed directly to the function
                                    referenced by the func argument (see the
                                    documentation for the corresponding
                                    redfish HttpClient method for details)
                                    with the following exception:  If kwargs
                                    contains a valid_status_codes key, it will
                                    be removed from kwargs and processed by
                                    this function.  This allows the caller to
                                    indicate what rest status codes are
                                    acceptable.  The default value is [200].
                                    See the valid_http_status_code function
                                    above for details.

        Example uses:

        From a python program:

        response =
        bmc_redfish.get("/redfish/v1/Managers/bmc/EthernetInterfaces", [200,
        201])

        If this call to the get method generates a response.status equal to
        anything other than 200 or 201, an exception will be raised.

        From a robot program:

        BMC_Redfish.logout
        ${response}=  BMC_Redfish.Get
        /redfish/v1/Managers/bmc/EthernetInterfaces  valid_status_codes=[401]

        As part of a robot test, the programmer has logged out to verify that
        the get request will generate a status code of 401 (i.e.
        "Unauthorized").
        """
        gp.qprint_executing(stack_frame_ix=3, style=gp.func_line_style_short)
        # Convert python string object definitions to objects (mostly useful
        # for robot callers).
        args = fa.args_to_objects(args)
        kwargs = fa.args_to_objects(kwargs)
        valid_status_codes = kwargs.pop('valid_status_codes', [200])
        response = func(*args, **kwargs)
        valid_http_status_code(response.status, valid_status_codes)
        return response

    # Define rest function wrappers.
    def get(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).get, *args,
                                 **kwargs)

    def head(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).head, *args,
                                 **kwargs)

    def post(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).post, *args,
                                 **kwargs)

    def put(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).put, *args,
                                 **kwargs)

    def patch(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).patch, *args,
                                 **kwargs)

    def delete(self, *args, **kwargs):
        return self.rest_request(super(redfish_plus, self).delete, *args,
                                 **kwargs)

    def __del__(self):
        del self
