from data_dispatcher.api import DataDispatcherClient
from metacat.webapi import MetaCatClient 
import sys, getopt, os, json
from .ui_project import create_project, show_project, list_projects
from .ui_handle import show_handle
from .ui_lib import pretty_json
from .ui_file import show_file, replica_available, replica_unavailable
import time

server_url = os.environ.get("DATA_DISPATCHER_URL")
if not server_url:
    print("Data Dispatcher Server URL undefined. Use DATA_DISPATCHER_URL environment variable")
    sys.exit(2)

my_name = sys.argv[0]

    
Usage = f"""
Usage:

dd <commnd> <subcommand> <options> <args>

Commands:

    worker [-n]                                         - print my worker_id. -n generates new one.
                                                          worker id will be saved in <CWD>/.worker_id
    create project ...
    show project ...
    list projects ...
    
    replica available ...
    replica unavailable ...

    show file [-j] <namespace>:<name>

    list handles [-s <status>] <project_id>                - list file handles, -s filters handles by status
    show handle [-j] <project_id> <namespace>:<name>       - show file handle, -j - as JSON

    next [-j] [-w <timeout>|-W] <project_id>               - get next available file, 
                                                             -j - as JSON
                                                             -w - wait for next file until "timeout" seconds
                                                             -W - wait for next file until the project finishes

    done <project_id> <namespace>:<name>                   - mark the file as successfully processed
    failed [-f] <project_id> <namespace>:<name>            - mark the file as failed, -f means "final", no retries

    delete project <project_id>
    
    login x509 <user> <cert> <key>
    login password <user>
"""

def main():
    client = DataDispatcherClient(server_url)

    if len(sys.argv[1:]) < 1 or "-\?" in sys.argv[1:] or "--help" in sys.argv[1:]:
        print(Usage)
        sys.exit(2)
    
    command = sys.argv[1]
    rest = sys.argv[2:]

    if command == "worker":
        if rest and rest[0] == "-n":
            worker_id = client.new_worker_id()
        else:
            worker_id = client.WorkerID
        if not worker_id:
            print("worker id unknown")
            sys.exit(1)
        print(worker_id)
        
    elif command == "create":
        subcommand, rest = rest[0], rest[1:]
        if subcommand != "project":
            print(Usage)
            sys.exit(2)
        create_project(client, rest)
    
    elif command == "show":
        subcommand, rest = rest[0], rest[1:]
        if subcommand not in ("file", "project", "handle"):
            print(Usage)
            sys.exit(2)
        if subcommand == "project":
            show_project(client, rest)
        elif subcommand == "handle":
            show_handle(client, rest)
        elif subcommand == "file":
            show_file(client, rest)
        else:
            print(Usage)
            sys.exit(2)
        
    elif command == "replica":
        subcommand, rest = rest[0], rest[1:]
        if subcommand == "available":
            replica_available(client, rest)
        elif subcommand == "unavailable":
            replica_unavailable(client, rest)
        else:
            print(Usage)
            sys.exit(2)

    elif command == "list":
        if not rest:
            print(Usage)
            sys.exit(2)
        subcommand, rest = rest[0], rest[1:]
        if subcommand == "projects":
            list_projects(client, rest)
        elif subcommand == "handles":
            list_handles(client, rest)
        else:
            print(Usage)
            sys.exit(2)
        
    elif command == "delete":
        subcommand, rest = rest[0], rest[1:]
        if subcommand == "project":
            project_id = rest[0]
            client.delete_project(project_id)
        else:
            print(Usage)
            sys.exit(2)
        

    elif command == "next":
        opts, args = getopt.getopt(rest, "jw:W")
        opts = dict(opts)
        if not args:
            print(Usage)
            sys.exit(2)
        project_id = args[0]
        as_json = "-j" in opts
        timeout = int(opts.get("-w", 0))
        if "-W" in opts:
            timeout = None
        wait = "-w" in opts or "-W" in opts
        done = False
        t0 = time.time()
        while not done:
            info = client.next_file(project_id)
            if info:
                if as_json:
                    print(pretty_json(info))
                else:
                    print("%s:%s" % (info["namespace"], info["name"]))
                sys.exit(0)
            if wait and (timeout is None or time.time() < t0 + timeout):
                project_info = client.get_project(project_id)
                if not project_info["active"]:
                    sys.exit(10)    # project finished
                time.sleep(5)
            else:
                sys.exit(11)        # timeout

    elif command == "done":
        if len(rest) != 2:
            print(Usage)
            sys.exit(2)
        project_id, did = rest
        client.file_done(project_id, did)
    
    elif command == "failed":
        opts, args = getopt.getopt(rest, "f")
        opts = dict(opts)
        if len(args) != 2:
            print(Usage)
            sys.exit(2)
        project_id, did = args
        client.file_failed(project_id, did, retry = not "-f" in opts)
    
    elif command == "login":
        if len(rest) < 2:
            print(Usage)
            sys.exit(2)
        subcommand, rest = rest[0], rest[1:]
        if subcommand == "x509":
            username, cert, key = rest
            user, expiration = client.login_x509(username, cert, key)
        elif subcommand == "password":
            import getpass
            username = rest[0]
            password = getpass.getpass("Password:")
            user, expiration = client.login_password(username, password)
        else:
            print(f"Unknown authentication mechanism {subcommand}\n")
            print(Usage)
            sys.exit(2)

        print ("User:   ", user)
        print ("Expires:", time.ctime(expiration))
    
    else:
        print(Usage)
        sys.exit(2)

if __name__ == "__main__":
    main()
        
        
    
            
            
        
        
        
        
        
