#!/usr/bin/python
#
# XOSAPI interactive shell


import argparse
import functools
import os, sys
import atexit
import readline
import rlcompleter

from twisted.internet import reactor
from xosapi.xos_grpc_client import InsecureClient, SecureClient, setup_logging, Empty

current_client = None

def parse_args():
    parser = argparse.ArgumentParser()

    defs = {"grpc_insecure_endpoint": "xos-core.cord.lab:50055",
            "grpc_secure_endpoint": "xos-core.cord.lab:50051",
            "consul": None}

    _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
    parser.add_argument(
        '-C', '--consul', dest='consul', action='store',
        default=defs['consul'],
        help=_help)

    _help = ('gRPC insecure end-point to connect to. It can either be a direct'
             'definition in the form of <hostname>:<port>, or it can be an'
             'indirect definition in the form of @<service-name> where'
             '<service-name> is the name of the grpc service as registered'
             'in consul (example: @voltha-grpc). (default: %s'
             % defs['grpc_insecure_endpoint'])
    parser.add_argument('-G', '--grpc-insecure-endpoint',
                        dest='grpc_insecure_endpoint',
                        action='store',
                        default=defs["grpc_insecure_endpoint"],
                        help=_help)

    _help = ('gRPC secure end-point to connect to. It can either be a direct'
             'definition in the form of <hostname>:<port>, or it can be an'
             'indirect definition in the form of @<service-name> where'
             '<service-name> is the name of the grpc service as registered'
             'in consul (example: @voltha-grpc). (default: %s'
             % defs["grpc_secure_endpoint"])
    parser.add_argument('-S', '--grpc-secure-endpoint',
                        dest='grpc_secure_endpoint',
                        action='store',
                        default=defs["grpc_secure_endpoint"],
                        help=_help)

    parser.add_argument('-u', '--username',
                        dest='username',
                        action='store',
                        default=None,
                        help=_help)

    parser.add_argument('-p', '--password',
                        dest='password',
                        action='store',
                        default=None,
                        help=_help)

    _help = 'omit startup banner log lines'
    parser.add_argument('-n', '--no-banner',
                        dest='no_banner',
                        action='store_true',
                        default=False,
                        help=_help)

    _help = "suppress debug and info logs"
    parser.add_argument('-q', '--quiet',
                        dest='quiet',
                        action='count',
                        help=_help)

    _help = 'enable verbose logging'
    parser.add_argument('-v', '--verbose',
                        dest='verbose',
                        action='count',
                        help=_help)

    args = parser.parse_args()

    return args

def login(username=None, password=None):
    if current_client:
        current_client.stop()
        current_client.session_change = True

    # now switch

    if username:
        client = SecureClient(endpoint=args.grpc_secure_endpoint, username=username, password=password)
        client.set_reconnect_callback(functools.partial(start_xossh, client))
        client.start()
    else:
        client = InsecureClient(endpoint=args.grpc_insecure_endpoint)
        client.set_reconnect_callback(functools.partial(start_xossh, client))
        client.start()

def setDirtyModels(*args, **kwargs):
    return current_client.utility.SetDirtyModels(current_client.utility_pb2.ModelFilter(*args, **kwargs))

def listDirtyModels(*args, **kwargs):
    return current_client.utility.ListDirtyModels(current_client.utility_pb2.ModelFilter(*args, **kwargs))

def listModelDefs():
    return current_client.modeldefs.ListModelDefs(Empty())

def listUtility():
    print 'setDirtyModels(class_name=None)'
    print 'listDirtyModels(class_name=None)'
    print 'listModelDefs()'

def examples():
    print 'coreapi.Slice.objects.all() # list all slices'
    print 's = Slice.objects.new() # create a new slice'
    print 's.name = "mysite_foo" # set a slice name'
    print 's.site_id = coreapi.Site.objects.all()[0].id # grab the first site'
    print 's.save() # save the slice'
    print

def start_xossh(client):
    global coreapi, current_client
    coreapi = client.xos_orm
    current_client = client

    current_client.session_change = False

    if not args.no_banner:
        print
        print "__   __   ____     _____    _____   _    _"
        print "\ \ / /  / __ \   / ____|  / ____| | |  | |"
        print " \ V /  | |  | | | (___   | (___   | |__| |"
        print "  > <   | |  | |  \___ \   \___ \  |  __  |"
        print " / . \  | |__| |  ____) |  ____) | | |  | |"
        print "/_/ \_\  \____/  |_____/  |_____/  |_|  |_|"
        print

        print "XOS Core server at %s" % client.endpoint

        print 'Type "listObjects()" for a list of all objects'
        print 'Type "listUtility()" for a list of utility functions'
        print 'Type "login("username", "password")" to switch to a secure shell'
        print 'Type "examples()" for some examples'

    # Load command history
    history_path = os.path.join(os.environ["HOME"], ".xossh_history")
    try:
        file(history_path, 'a').close()
        readline.read_history_file(history_path)
        atexit.register(readline.write_history_file, history_path)
    except IOError:
        pass

    # Enable tab completion
    readline.parse_and_bind("tab: complete")

    reactor.callLater(0, functools.partial(do_xossh_prompt, client))

def do_xossh_prompt(client):
    for k in client.xos_orm.all_model_names:
        locals()[k] = getattr(client.xos_orm, k)

    locals()["listObjects"] = client.xos_orm.listObjects

    prompt = "xossh "
    try:
        while True:
            command = ""
            while True:
                # Get line
                try:
                    if command == "":
                        sep = ">>> "
                    else:
                        sep = "... "
                    line = raw_input(prompt + sep)
                # Ctrl-C
                except KeyboardInterrupt:
                    command = ""
                    print
                    break

                # Build up multi-line command
                command += line

                # Blank line or first line does not end in :
                if line == "" or (command == line and line[-1] != ':'):
                    break

                command += os.linesep

            # Quit
            if command in ["q", "quit", "exit"]:
                reactor.stop()
                return

            if command == "":
                # blank line
                pass
            else:
                try:
                    # Do it
                    code = compile(command, "<stdin>", "single")
                    exec code
                except Exception, err:
                    print err

            # check to see if login() was used
            if client.session_change:
                return

            #reactor.callLater(0, functools.partial(do_xossh_prompt, client))

    except EOFError:
        print
        reactor.stop()

def main():
    global args
    args = parse_args()

    setup_logging(args)

    login(username=args.username, password=args.password)
    reactor.run()

if __name__ == "__main__":
    main()
