import argparse
from argparse import RawTextHelpFormatter
import threading
import time

from .api import CKANAPI
from .upload import task


def monitor_upload_progress(upload_job):
    newline = False
    while upload_job.state == "parcel":
        time.sleep(1)
    while upload_job.state == "transfer":
        print(upload_job.get_progress_string(), end="\r", flush=True)
        newline = True
        time.sleep(1)
    if newline:
        # Only print new line if we printed something before.
        print("")


def ascertain_state_or_bust(upload_job, state):
    """If `upload_job.state != `state`, raise an exception"""
    if upload_job.state != state:
        if upload_job.state == "error":
            print(f"Job {upload_job} encountered an error:")
            print(upload_job.traceback)
            raise ValueError("See message above!")
        else:
            raise ValueError(
                f"The upload job {upload_job} should be in the state "
                + f"'{state}', but it's state is '{upload_job.state}'!"
            )


def upload_task(path_task=None, server=None, api_key=None, ret_job=False):
    """Upload a .dcoraid-task file to a DCOR instance"""
    if path_task is None or server is None or api_key is None:
        parser = upload_task_parser()
        args = parser.parse_args()
        path_task = args.path_task
        server = args.server
        api_key = args.api_key

    print("Initializing.")
    # set up the api
    api = CKANAPI(server, api_key=api_key)
    # load the .dcoraid-task file
    uj = task.load_task(path_task,
                        api=api,
                        update_dataset_id=True)
    print(f"Dataset ID is {uj.dataset_id}.")
    print("Compressing resources.")
    uj.task_compress_resources()
    ascertain_state_or_bust(uj, "parcel")

    print("Uploading resources.")
    # thread that prints the upload progress
    monitor_thread = threading.Thread(target=monitor_upload_progress,
                                      name="Upload Monitor",
                                      args=(uj,),
                                      daemon=True)
    monitor_thread.start()
    uj.task_upload_resources()
    monitor_thread.join()
    ascertain_state_or_bust(uj, "online")
    print("Verifying upload.")
    uj.task_verify_resources()
    ascertain_state_or_bust(uj, "done")
    print("Done.")
    if ret_job:
        return uj


def upload_task_parser():
    descr = (
        "Upload a .dcoraid-task file to a DCOR instance. Example usage::\n"
        + "\n    dcoraid-upload-task upload_job.dcoraid-task "
        + "dcor-dev.mpl.mpg.de eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiO"
        )
    parser = argparse.ArgumentParser(description=descr,
                                     formatter_class=RawTextHelpFormatter)
    parser.add_argument('path_task', metavar="PATH", type=str,
                        help='The .dcoraid-task file')
    parser.add_argument('server', metavar="SERVER", type=str,
                        help='DCOR instance to upload to')
    parser.add_argument('api_key', metavar="API_KEY", type=str,
                        help='Your DCOR API key or token')
    return parser
