#!/usr/bin/env python3
#
# SPDX-License-Identifier: BSD-3-Clause
# Depthcharge: <https://github.com/nccgroup/depthcharge>
#
# Ignore warnings that aren't particularly meaningful in this script:
#   pylint: disable=missing-module-docstring,,invalid-name,redefined-outer-name
#

import sys

from argparse import RawDescriptionHelpFormatter
from os.path import basename

from depthcharge.cmdline import ArgumentParser
from depthcharge.hunter import CommandTableHunter

_LONGHELP_TEXT = 'Value of U-Boot CONFIG_SYS_LONGHELP setting.'
_AUTOCOMPLETE_TEXT = 'Value of U-Boot CONFIG_AUTO_COMPLETE setting.'

_USAGE = '{:s} [options] -f <image file>'.format(basename(__file__))

_DESCRIPTION = """
Search for U-Boot command tables within a memory or flash dump.
"""

_EPILOG = """
notes:
  If the --longhelp and --autocomplete options are not specified, Depthcharge
  will attempt to infer the state of these compile-time configuration settings.

  When --subcmds is specified, output will include any subcommand handler tables.
  This may require a lower --threshold setting, which could yield false positives.


example:
  Search for command table entries provide detailed output, given an ARM
  device and a memory dump taken from address 0x87800000.

    depthcharge-find-cmd --arch arm -a 0x8780000 -f dump.bin --details
\r
"""


def handle_cmdline():
    """
    Parse and return command line arguments
    """

    cmdline = ArgumentParser(init_args=['address', 'arch', 'file'],
                             address_required=True, address_default=None,
                             file_required=True,
                             file_help='Flash or memory image to inspect',
                             formatter_class=RawDescriptionHelpFormatter,
                             usage=_USAGE, description=_DESCRIPTION, epilog=_EPILOG)

    cmdline.add_argument('--longhelp',
                         choices=['Y', 'N'],
                         default=None,
                         help=_LONGHELP_TEXT)

    cmdline.add_argument('--autocomplete',
                         choices=['Y', 'N'],
                         default=None,
                         help=_AUTOCOMPLETE_TEXT)

    cmdline.add_argument('--threshold',
                         type=int,
                         default=5,
                         help='Minimum table size to report. Default: 5')

    cmdline.add_argument('--subcmds',
                         action='store_true',
                         default=False,
                         help='Include sub-command tables in displayed results')

    cmdline.add_argument('--details',
                         action='store_true',
                         default=False,
                         help='Display more detailed output')

    args = cmdline.parse_args()

    if args.longhelp is not None:
        args.longhelp = args.longhelp == 'Y'

    if args.autocomplete is not None:
        args.autocomplete =  args.autocomplete == 'Y'

    return args


if __name__ == '__main__':
    args = handle_cmdline()

    with open(args.file, 'rb') as infile:
        image_data = infile.read()

    try:
        hunter = CommandTableHunter(image_data, args.address, arch=args.arch)
    except (ValueError, TypeError) as e:
        print('Failed to create depthcharge.CommandTableHunter', str(e), file=sys.stderr)
        sys.exit(1)

    to_str = hunter.result_str if args.details else hunter.result_summary_str
    finditer = hunter.finditer(None,
                               threshold=args.threshold,
                               longhelp=args.longhelp,
                               autocomplete=args.autocomplete)

    for result in finditer:
        if not result['is_subcmd_table'] or args.subcmds:
            print(to_str(result))
