import requests_html, openpyxl, ntpath, os, datetime, pkg_resources, sys
import numpy as np
import pandas as pd
from pathlib import Path
from bs4 import BeautifulSoup as BSoup
from requests.exceptions import ConnectionError
from requests.exceptions import ReadTimeout
from openpyxl.utils.dataframe import dataframe_to_rows
from boldigger.boldblast_coi import slices, fasta_to_string, post_request, save_as_df, save_results, fasta_rewrite
from boldigger_cline.login import login
from tqdm import tqdm

def requests(url_list):

    html = []

    with requests_html.HTMLSession() as session:
        for url in tqdm(url_list, desc = 'Downloading results'):
            r = session.get(url)
            html.append(r.text)

    return html

def main(username, password, fasta_path, output_path, query_length):

    ## import data needed for the requests
    certs = pkg_resources.resource_filename(__name__, 'data/certs.pem')

    ## create session for identificaton engine to save userdata
    session = login(username, password, certs)
    querys, sequences_names = fasta_to_string(fasta_path, query_length)

    ## flags to check request status
    error = False

    ## request as long as there are querys left
    for query in tqdm(querys, desc = 'Requesting BOLD'):

        ## stop if there are 3 connectionerrors or timeouts
        error_count = 0

        ## request until you get a good answer from the server
        while error_count < 3:
            tqdm.write('%s: Requesting BOLD. This will take a while.' % datetime.datetime.now().strftime("%H:%M:%S"))

            ## try to get a answer from bold server, repeat in case of timeout
            try:
                links = post_request(query, session)
            except ConnectionError:
                tqdm.write('%s: ConnectionError, BOLD did not respond properly: Trying to reconnect.' % datetime.datetime.now().strftime("%H:%M:%S"))
                error_count += 1
                continue
            except ReadTimeout:
                tqdm.write('%s: Readtimeout, BOLD did not respond in time: Trying to reconnect.' % datetime.datetime.now().strftime("%H:%M:%S"))
                error_count += 1
                continue
            break
        else:
            error = True

        if not error:
            ## download data from the fetched links
            html_list = requests(links)

            ## parse the returned html
            tqdm.write('%s: Parsing html.' % datetime.datetime.now().strftime("%H:%M:%S"))
            dataframes = save_as_df(html_list, sequences_names[querys.index(query)])

            ## save results in resultfile
            tqdm.write('%s: Saving results.' % datetime.datetime.now().strftime("%H:%M:%S"))
            save_results(dataframes, fasta_path, output_path)

            ## remove found OTUS from fasta and write it into a new one
            tqdm.write('%s: Removing finished OTUs from fasta.' % datetime.datetime.now().strftime("%H:%M:%S"))
            fasta_rewrite(fasta_path, query_length)

        else:
            tqdm.write('%s: Too many bad connections. Try a smaller batch size. Close to continue.' % datetime.datetime.now().strftime("%H:%M:%S"))
            sys.exit()

    if not error:
        tqdm.write('%s: Done.' % datetime.datetime.now().strftime("%H:%M:%S"))
