#!/usr/bin/env python

import os
import sys
import argparse
from hunter import trace, Q
from xunter import CallPrinterProfile, StackPrinterProfile

def xunter_help():
    print('Xunter was made for tracing xonsh via python-hunter.')
    print("Example: xunter --no-rc -c '2+2' ++depth-lt 10")
    print("Example: git clone xonsh; cd xonsh; xunter --no-rc -c '2+2' ++depth-lt 10 ++cwd")
    print("Example: xunter --no-rc -c '2+2' ++depth-lt 10 ++output /tmp/22.xunter")
    print("Example: xunter --no-rc -c '2+2' ++depth-lt 10 ++filter 'Q(filename_has=\"main.py\")'")
    print()


def argparse_xunter():
    parser = argparse.ArgumentParser(prefix_chars='-+')
    parser.add_argument('++cwd', action='store_true', help='Append current working directory to PATH.')
    parser.add_argument('++time-sec-gt', help="Show rows with time in seconds greater than.")
    parser.add_argument('++depth-lt', help="Trace depth. The same as `++filter 'Q(depth_lt=5)'`.")
    parser.add_argument('++printer', default=os.environ.get('XUNTER_PRINTER', 'stack'), help="Printer: `stack` or `call`. Default: `stack`.")
    parser.add_argument('++stdlib', action='store_true', help='Trace stdlib. Default: no.')
    parser.add_argument('++output', default=os.environ.get('XUNTER_OUTPUT', 'stderr'), help='Output: `stdout`, `stderr` or filepath. Default: `stderr`.')
    parser.add_argument('++filter', default='()', help='Hunter filters: https://python-hunter.readthedocs.io/en/latest/filtering.html')
    parser.add_argument('++debug', action='store_true', help='Debug mode for xunter.')

    if '--help' in sys.argv:
        xunter_help()
        parser.print_help()
        print('\nXonsh help:\n')
        return

    debug = '++debug' in sys.argv

    if debug:
        print('Args input:', sys.argv, file=sys.stderr)

    args, left = parser.parse_known_args()
    sys.argv = sys.argv[:1]+left

    if debug:
        print('Args to xonsh:', sys.argv, file=sys.stderr)

    return args

if x := argparse_xunter():
    for a in sys.argv:
        if a[:2] == '++':
            print(f'Unknown xunter argument: {a}')
            sys.exit(1)

    if x.cwd:
        sys.path.insert(0, os.getcwd())

    if x.printer == 'call':
        printer = CallPrinterProfile
    elif x.printer == 'stack':
        printer = StackPrinterProfile
    else:
        raise Exception('Unknown printer')

    if x.output:
        if x.output == 'stdout':
            printer.overwrite_stream = sys.stdout
        elif x.output == 'stderr':
            printer.overwrite_stream = sys.stderr
        else:
            printer.overwrite_stream = open(x.output, 'w')
    if x.time_sec_gt:
        printer.filter_time_sec_gt = float(x.time_sec_gt)
        if x.debug:
            print(f'printer.filter_time_sec_gt={printer.filter_time_sec_gt}')

    filters = eval(x.filter)
    if type(filters) is not tuple:
        filters = (filters, )

    if x.depth_lt:
        filters = filters + (Q(depth_lt=int(x.depth_lt)),)

    if x.debug:
        print('Filters:', filters, file=sys.stderr)

    trace(
        *filters,
        action=printer,
        stdlib=x.stdlib
    )

# From `cat @$(which xonsh)`:
import re
import sys
from xonsh.main import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

