# Copyright 2020, castLabs GmbH

from .. import __version__
from ..core.failure import die
from ..vmp import VMP
from argparse import ArgumentParser
from sys import argv
from os import environ, path

################################################################################

def main():
  try:
    bp = ArgumentParser(path.basename(argv[0]))
    bp.add_argument('-v', '--version', action='version', version=f'%(prog)s {__version__}')
    bp.add_argument('-n', '--no-ask', help='enable non-interactive mode',
      action='store_true', default='EVS_NO_ASK' in environ
    )
    bp.add_argument('-a', '--any-ski', help='verify any subject key identifier',
      action='store_true', default='EVS_ANY_SKI' in environ
    )

    _kind = ArgumentParser(add_help=False)
    _kind.set_defaults(kind=environ.get('EVS_KIND', 'streaming'))
    _kind.add_argument('-s', '--streaming', help='streaming only signature (default)',
      dest='kind', action='store_const', const='streaming'
    )
    _kind.add_argument('-p', '--persistent', help='streaming and persistent download signature',
      dest='kind', action='store_const', const='persistent'
    )
    _flags = ArgumentParser(add_help=False)
    _flags.add_argument('-i', '--intermediate', help='generate intermediate signature',
      dest='intermediate', action='store_true', default='EVS_INTERMEDIATE' in environ
    )
    _min_days = ArgumentParser(add_help=False)
    _min_days.add_argument('-M', '--min-days', help='minimum number of remaining valid days',
      type=int, default=environ.get('EVS_MIN_DAYS', 90)
    )
    _force = ArgumentParser(add_help=False)
    _force.add_argument('-f', '--force', help='force new signature',
      action='store_true', default='EVS_FORCE' in environ
    )
    _gz = ArgumentParser(add_help=False)
    _gz.add_argument('-z', '--gz', help='request gzip upload (slower for fast connections)',
      action='store_true', default='EVS_GZ' in environ
    )
    _cred = ArgumentParser(add_help=False)
    _cred.add_argument('-A', '--account-name', help='provide account name [CACHED]',
      default=environ.get('EVS_ACCOUNT_NAME')
    )
    _cred.add_argument('-P', '--passwd', help='provide account password',
      default=environ.get('EVS_PASSWD')
    )
    _transfer = ArgumentParser(add_help=False)
    _transfer_grp = _transfer.add_argument_group('transfer options')
    _transfer_grp.add_argument('--connect-timeout',
      help=f'connection timeout in seconds (default: {VMP.DEFAULT_CONNECT_TIMEOUT})',
      type=float, default=environ.get('EVS_CONNECT_TIMEOUT', VMP.DEFAULT_CONNECT_TIMEOUT)
    )
    _transfer_grp.add_argument('--auth-timeout',
      help=f'auth request timeout in seconds (default: {VMP.DEFAULT_AUTH_TIMEOUT})',
      type=float, default=environ.get('EVS_AUTH_TIMEOUT', VMP.DEFAULT_AUTH_TIMEOUT)
    )
    _transfer_grp.add_argument('--upload-url-timeout',
      help=f'upload URL request timeout in seconds (default: {VMP.DEFAULT_UPLOAD_URL_TIMEOUT})',
      type=float, default=environ.get('EVS_UPLOAD_URL_TIMEOUT', VMP.DEFAULT_UPLOAD_URL_TIMEOUT)
    )
    _transfer_grp.add_argument('--upload-timeout',
      help=f'upload request timeout in seconds (default: {VMP.DEFAULT_UPLOAD_TIMEOUT})',
      type=float, default=environ.get('EVS_UPLOAD_TIMEOUT', VMP.DEFAULT_UPLOAD_TIMEOUT)
    )
    _transfer_grp.add_argument('--sign-timeout',
      help=f'sign request timeout in seconds (default: {VMP.DEFAULT_SIGN_TIMEOUT})',
      type=float, default=environ.get('EVS_SIGN_TIMEOUT', VMP.DEFAULT_SIGN_TIMEOUT)
    )
    _transfer_grp.add_argument('--multipart-threshold',
      help=f'multipart upload threshold in MB (default: {VMP.DEFAULT_MULTIPART_THRESHOLD}, min: {VMP.MULTIPART_MIN_SIZE})',
      type=int, default=environ.get('EVS_MULTIPART_THRESHOLD', VMP.DEFAULT_MULTIPART_THRESHOLD)
    )
    _transfer_grp.add_argument('--multipart-part-size',
      help=f'multipart upload part size in MB (default: {VMP.DEFAULT_MULTIPART_PART_SIZE}, min: {VMP.MULTIPART_MIN_SIZE})',
      type=int, default=environ.get('EVS_MULTIPART_PART_SIZE', VMP.DEFAULT_MULTIPART_PART_SIZE)
    )
    _transfer_grp.add_argument('--multipart-retries',
      help=f'multipart upload max retries (default: {VMP.DEFAULT_MULTIPART_RETRIES})',
      type=int, default=environ.get('EVS_MULTIPART_RETRIES', VMP.DEFAULT_MULTIPART_RETRIES)
    )
    _transfer_grp.add_argument('--multipart-max-concurrency',
      help=f'multipart upload max concurrent connections (default: {VMP.DEFAULT_MULTIPART_MAX_CONCURRENCY})',
      type=int, default=environ.get('EVS_MULTIPART_MAX_CONCURRENCY', VMP.DEFAULT_MULTIPART_MAX_CONCURRENCY)
    )

    _name_hint = ArgumentParser(add_help=False)
    _name_hint.add_argument('-H', '--name-hint', help='provide name hint',
      default=environ.get('EVS_NAME_HINT')
    )

    _assets = ArgumentParser(add_help=False)
    _assets.add_argument('bin', help='path to binary')
    _assets.add_argument('sig', help='path to signature', nargs='?')
    _pkgs = ArgumentParser(add_help=False)
    _pkgs.add_argument('pkg', help='path to electron package directory', nargs='+')

    sp = bp.add_subparsers(title='commands', dest='command', required=True)
    cp = sp.add_parser('verify', help='verify signature',
      aliases=['v'],
      parents=[_kind, _flags, _min_days, _assets]
    )
    cp.set_defaults(command=VMP.verify)
    cp = sp.add_parser('sign', help='refresh signature',
      aliases=['s'],
      parents=[_kind, _flags, _min_days, _force, _gz, _cred, _transfer, _assets]
    )
    cp.set_defaults(command=VMP.sign)
    cp = sp.add_parser('verify-pkg', help='verify electron package signature',
      aliases=['vp'],
      parents=[_kind, _name_hint, _min_days, _pkgs]
    )
    cp.set_defaults(command=VMP.verify_pkg)
    cp = sp.add_parser('sign-pkg', help='refresh electron package signature',
      aliases=['sp'],
      parents=[_kind, _name_hint, _min_days, _force, _gz, _cred, _transfer, _pkgs]
    )
    cp.set_defaults(command=VMP.sign_pkg)

    args = vars(bp.parse_args())
    vmp = VMP(no_ask=args.pop('no_ask'), any_ski=args.pop('any_ski'),
              connect_timeout=args.pop('connect_timeout', None),
              auth_timeout=args.pop('auth_timeout', None),
              upload_url_timeout=args.pop('upload_url_timeout', None),
              upload_timeout=args.pop('upload_timeout', None),
              sign_timeout=args.pop('sign_timeout', None),
              multipart_threshold=args.pop('multipart_threshold', None),
              multipart_part_size=args.pop('multipart_part_size', None),
              multipart_retries=args.pop('multipart_retries', None),
              multipart_max_concurrency=args.pop('multipart_max_concurrency', None))
    run = args.pop('command')
    run(vmp, **args)
  except (Exception, KeyboardInterrupt) as e:
    die(e)

################################################################################
