"""iDRAC reset a chassis power state.

python idrac_ctl.py chassis-reset --reset_type ForceOff

Author Mus spyroot@gmail.com
"""
import asyncio
import json
from abc import abstractmethod
from typing import Optional

from base import IDracManager, ApiRequestType, Singleton
from base import CommandResult, InvalidArgument
from base import FailedDiscoverAction, PostRequestFailed


class ChassisReset(IDracManager,
                   scm_type=ApiRequestType.ChassisReset,
                   name='reboot',
                   metaclass=Singleton):
    """
    """

    def __init__(self, *args, **kwargs):
        super(ChassisReset, self).__init__(*args, **kwargs)

    @staticmethod
    @abstractmethod
    def register_subcommand(cls):
        """Register command
        :param cls:
        :return:
        """
        cmd_parser = cls.base_parser(is_file_save=False, is_expanded=False)
        cmd_parser.add_argument('--reset_type',
                                required=False, dest='reset_type',
                                default="On", type=str,
                                help="On, ForceOff. On will change power state on.")

        help_text = "command reset chassis"
        return cmd_parser, "chassis-reset", help_text

    def execute(self,
                reset_type: Optional[str] = "On",
                do_async: Optional[bool] = False,
                data_type: Optional[str] = "json",
                **kwargs
                ) -> CommandResult:
        """
        :param do_async:
        :param data_type:
        :param reset_type: "On, ForceOff"
        :param kwargs:
        :return: return cmd result
        :raise FailedDiscoverAction
        """
        headers = {}
        if data_type == "json":
            headers.update(self.json_content_type)

        chassis_data = self.sync_invoke(ApiRequestType.ChassisQuery, "chassis_service_query")
        redfish_action = chassis_data.discovered['Reset']

        target_api = redfish_action.target
        args = redfish_action.args
        args_options = args['ResetType']
        if reset_type not in args_options:
            raise InvalidArgument(f"Unsupported reset type {reset_type} "
                                  f"supported reset options {args_options}.")

        if target_api is None:
            FailedDiscoverAction("Failed discover reset chassis actions.")

        payload = {'ResetType': reset_type}
        r = f"https://{self.idrac_ip}{target_api}"

        ok = False
        try:
            if not do_async:
                response = self.api_post_call(r, json.dumps(payload), headers)
                ok = self.default_post_success(self, response)
            else:
                loop = asyncio.get_event_loop()
                ok, response = loop.run_until_complete(self.async_post_until_complete(r, json.dumps(payload), headers))
        except PostRequestFailed as prf:
            print(prf)
            pass

        return CommandResult(self.api_success_msg(ok), None, None)
