# File: blast.py
#
# Description:
# Performs a blast on the fasta sequence passed in from the command line and
# the searches NCBI protein database and UniProt for the EC number of the 
# top BLAST hits.
#
# Author: <NAME>

from Bio import SeqIO
from Bio.Blast import NCBIWWW
from time import sleep
import sys
from utils import *
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)


def parse_args():
    """
    Parses the arguments to the program.
    
    :return: A dictionary of arguements
    """
    # Expected arguments
    outFile = None
    sleep_time  = None
    fasta_sequence  = None
    email  = None
    min_pct_idnt  = 97.0
    min_qry_cvr = 95.0
    max_blast_hits = 10
    max_uniprot_hits = 50
    # Dict to hold arguements
    args =  {
                '--fasta_sequence' : fasta_sequence,
                '--program' : 'bastx',
                '--email' : email, 
                '--out_file' : outFile,
                '--min_pct_idnt' : min_pct_idnt,
                '--min_qry_cvr' : min_qry_cvr,
                '--max_blast_hits' : max_blast_hits,
                '--max_uniprot_hits' : max_uniprot_hits,
                '--sleep_time' : sleep_time,
                '--id' : '0',
            }
    received = set(())
    required    = set(('--fasta_sequence', '--email', '--program'))
    float_args  = set(('--sleep_time', '--min_pct_idnt', '--min_qry_cvr'))
    int_args    = set(('--max_blast_hits', '--max_uniprot_hits'))
    if len(sys.argv) % 2 != 1:
        print("Invalid command line arguements")
        exit()
    # Parse the arguements
    for i in range(1, len(sys.argv), +2):
        arg = sys.argv[i]
        val = sys.argv[i+1]
        if arg in args:
            received.add(arg)
            if arg in float_args:
                args[arg] = float(val)
            elif arg in int_args:
                args[arg] = int(val)
            elif arg in args:
                args[arg] = val
    # Check that the required arguments where passed in
    for r in required:
        if not r in received:
            print(r + " is a required arguement\n")
            print_usage()
            exit()
    return args
    
    
def print_usage():
    """
    Prints the usage statement
    """
    print("Usage:")
    print("  py blast.py --fasta_sequence <fasta sequence to blast>") 
    print("              --email <the user's email>")
    print("              --out_file <filepath to store result>")
    print("              --min_pct_idnt <the min % identity to use for blast hit>")
    print("              --min_qry_cvr <the min query cover to use for blast hit>") 
    print("              --max_blast_hits <the max number of blast hits to use>") 
    print("              --max_uniprot_hits <the max number of UniProt hits to use>")
    print("              --sleep_time <amount of time to sleep before preforming the blast>")
    print("")
    print("  Required params:\n\t--fasta_sequence\n\t--email")
    

args = parse_args()  
# BLAST requests that we don't flood the servers
if args['--sleep_time'] is not None:
    sleep(args['--sleep_time'])

# Perform the BLAST query
result_handle = NCBIWWW.qblast(program=args['--program'], 
                                      database="nr", 
                                      sequence=args['--fasta_sequence'])
blast_xml = result_handle.read()
result_handle.close()
# Process the blast results
seq_len = len(args['--fasta_sequence'])
output = prcs_blast_rslts(blast_xml, args)
if args['--out_file'] is None:
    print(output)
else:
    save_file = open(args['--out_file'], "w")
    save_file.write(output)
    save_file.close()