import argparse
import sys



class CustomArgumentParser(argparse.ArgumentParser):

    CLI_ACTION_DISCOVER = "discover"
    CLI_ACTION_SEND = "send"

    def __init__(self, argv=None, **kwargs):
        super().__init__(**kwargs)
        self.argv = argv if argv is not None else sys.argv[1:]

        subparsers = self.add_subparsers(dest='cli_action', help="Available actions")
        subparsers._parser_class = self.create_subparser  # Use a factory method for subparsers

        parser_discover = subparsers.add_parser(self.CLI_ACTION_DISCOVER, help="Discover Apple VDM's based on the given arguments")
        parser_discover.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0)
        parser_discover.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='')
        parser_discover.add_argument("-a", "--action", help="The Action to be included in the VDM", type=self.auto_int, metavar='', default=None)
        parser_discover.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug
        
        parser_send = subparsers.add_parser(self.CLI_ACTION_SEND, help="Sends the resulting Apple DFU VDM")
        parser_send.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0)
        parser_send.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='')
        parser_send.add_argument("-a", "--action", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='')
        parser_send.add_argument("-r", "--action_argument", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='')
        parser_send.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug
        parser_send.add_argument("-x", "--send", help="Actually send the vdm", action='store_true')

        self.parsed_args = self.parse_args(self.argv[1:])

        #Ensure the user provided a subparser argument (discovered, send)
        self.cli_action = self.parsed_args.cli_action
        if self.cli_action is None:
            self.print_help()
            sys.exit(255)

        self.action = self.parsed_args.action
        self.port = self.parsed_args.port
        self.sn = self.parsed_args.device
        self.sop = self.parsed_args.sop

        if self.CLI_ACTION_SEND == self.cli_action:
            self.action_argument= self.parsed_args.action_argument
            self.send = self.parsed_args.send

    def create_subparser(self, **kwargs):
        return argparse.ArgumentParser(**kwargs)

    def print_example_usage(self):

        EXAMPLE_USAGE = [ \
        (""), \
        ("Example Usage:"), \
        ("    \"%s discover -p 5\" - Discovers all Actions and Action Arguments"  % (self.argv[0])), \
        ("    \"%s discover -p 5 -d 0xBEEFFEED\" - Discovers all Actions and Action Arguments for the specified device"  % (self.argv[0])), \
        ("    \"%s discover -p 5 -a 0x106\" - Discovers Action Arguments for the provided action"  % (self.argv[0])), \
        (""), \
        ("    Note: Action (-a) and Action Arguments (-r) are not verified before sending."), \
        ("    \"%s send -p 5 -a 0x0106 -r 0x8001\" - Constructs an Apple DFU VDM, but does not send it."  % (self.argv[0])), \
        ("    \"%s send -p 5 -a 0x0106 -r 0x8001 -x\" - Constructs an Apple DFU VDM and Sends it"  % (self.argv[0])), \
        ]

        for usage in EXAMPLE_USAGE:
            print(usage)

    def print_help(self):
        super().print_help()
        self.print_example_usage()

    @staticmethod
    def auto_int(x):
        # Automatically detect the base (hex if prefixed with '0x', decimal otherwise)
        return int(x, 0)
        

