#!python

from __future__ import print_function

from configargparse import Action, ArgParser
from requests.exceptions import ConnectionError
import sys

from variantgrid_api.add_classification import add_classification_handle_args 
from variantgrid_api.annotation import annotation_handle_args
from variantgrid_api.classifications import classifications_handle_args
from variantgrid_api.shariant_classification import shariant_classifications_handle_args
from variantgrid_api.shariant_classification_modify import shariant_classifications_modify_handle_args
from variantgrid_api.gene_list import gene_list_handle_args


class ClassificationAction(Action):
    VALID_CLASSIFICATIONS = range(1, 6)
    def __call__(self, parser, namespace, values, option_string=None):
        if values not in self.VALID_CLASSIFICATIONS:
            valid_classifications_str = ','.join(map(str, self.VALID_CLASSIFICATIONS))
            raise ValueError("classification must be one of %s" % valid_classifications_str)
        setattr(namespace, self.dest, values)

def add_authentication(parser, required):
    parser.add("--user", required=required, env_var='VG_USER')
    parser.add("--password", required=required, env_var='VG_PASSWORD')
    parser.add("--basic_auth", action='store_true', env_var='VG_BASIC_AUTH', help='(Only needed for non shariant server) Set to true to just use username and password, otherwise oauth will be attempted')
    parser.add("--oauth_url", default='https://shariant.org.au/auth/realms/agha/protocol/openid-connect/token', env_var='VG_OAUTH', help='(Only needed for non shariant server) Address of where to get the token for oauth')
    parser.add("--client_id", default='shariant-client-tools', env_var="VG_CLIENT_ID", help='(Only needed for non shariant server) OAuth Client ID to request token against')


def get_args():
    # CLASSIFICATION_HELP = 'HGNC classifications: 1 - Benign, 2 - Likely benign, 3 - VUS, 4 - Likely Pathogenic, 5 - Pathogenic'
    
    parser = ArgParser(default_config_files=['~/.vg_api'])
    parser.add('-c', '--config', is_config_file=True, help='config file path')

    # Global settings

    parser.add("--host", default='https://shariant.org.au', env_var='VG_HOST', help='Server Address (default=https://shariant.org.au)')
    parser.add("--verbose", action='store_true', env_var='VG_VERBOSE', help='Print debugging information')

    subparsers = parser.add_subparsers(help='sub-command help', dest='command')
    
    # Add Classification
    # add_classification_parser = subparsers.add_parser('add_classification', help='Add new classification for a variant')
    # add_authentication(add_classification_parser, required=True)
    # variant_group = add_classification_parser.add_mutually_exclusive_group(required=True)
    # variant_group.add_argument('--variant', help='hg19 coordinate eg "1:169519049 T>C"') 
    # variant_group.add_argument('--dbsnp', help='dbSNP rsId eg "rs6025"')
    # variant_group.add_argument('--hgvs', help='HGVS string eg "F5 (NM_000130) p.Gln534Arg/c.1601A>G"')   
    # add_classification_parser.add_argument('--classification', type=int, action=ClassificationAction, help=CLASSIFICATION_HELP) 
    # add_classification_parser.add_argument('--public', action='store_true', default=False, help="Classification is public (default=False)") 

    classification_upload_parser = subparsers.add_parser('classification_upload', help="Create/Update a classification in Shariant")
    add_authentication(classification_upload_parser, required=True)
    classification_upload_parser.add_argument("--method", default="POST", help="POST or PATCH")
    classification_upload_parser.add_argument("--id", help="Id of the record, for new record provide own id prefixed by L_ or omit")

    # Classifications
    # classifications_parser = subparsers.add_parser('classifications', help='Get classification from VariantGrid')
    # add_authentication(classifications_parser, required=False)
    # classifications_parser.add_argument("--classification", type=int, action=ClassificationAction)
    # group = classifications_parser.add_mutually_exclusive_group(required=True)
    # group.add_argument("--all", action='store_true')
    # group.add_argument("--dbsnp")
    # group.add_argument("--gene")
    # group.add_argument("--locus")
    # group.add_argument("--variant")

    # Classifications
    classifications_parser = subparsers.add_parser('classifications', help="Retrieve classifications from Shariant")
    add_authentication(classifications_parser, required=True)
    classifications_parser.add_argument("--version", default=None, help="Version of the record")
    group = classifications_parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--all", action='store_true')
    group.add_argument("--keys", action='store_true')
    group.add_argument("--id")
    
    group = classifications_parser.add

    # Annotation
    annotation_parser = subparsers.add_parser('annotation', help='Get VariantGrid Annotations')

    group = annotation_parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--gene-id")
    group.add_argument("--gene")
    group.add_argument("--variant")
    # TODO: Annotation Versions??
    
    # Gene List
    gene_list_parser = subparsers.add_parser('gene_list', help='Get Gene List')
    add_authentication(gene_list_parser, required=False)
    gene_list_parser.add_argument("--category", default='Uploaded', help="One of 'Diagnostic', 'Uploaded'")
    group = gene_list_parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--pk")
    group.add_argument("--name")

    return parser.parse_args()


def main(args):
    SUBCOMMAND_HANDLERS = {
        "annotation" : annotation_handle_args,
        "add_classification" : add_classification_handle_args,
        "classifications": shariant_classifications_handle_args,
        "classification_upload": shariant_classifications_modify_handle_args,
        # "classifications" : classifications_handle_args,
        "gene_list" : gene_list_handle_args,
    }
    
    handler = SUBCOMMAND_HANDLERS[args.command or '<no command given>']
    try:
        return handler(args)
    except ConnectionError as nce:
        if args.verbose:
            msg = str(nce)
        else:
            msg = "Could not connect to server." 
        print(msg, file=sys.stderr)
        return 1


if __name__ == "__main__":
    args = get_args()
    main(args)