#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""     
    nubo
    ====

    CLI interface to multiple cloud providers.

    :copyright: (C) 2013 by Emanuele Rocca.
"""

import sys
import argparse
import readline

from nubo.config import write_config, read_config
from nubo.clouds.base import supported_clouds, get_cloud, CLOUDS_MAPPING

from texttable import Texttable

def rlinput(prompt, prefill=''):
    readline.set_startup_hook(lambda: readline.insert_text(prefill))
    try:
        return raw_input(prompt)
    except (KeyboardInterrupt, EOFError):
        print
        sys.exit(0)
    finally:
        readline.set_startup_hook()

def config(args):
    sclouds = supported_clouds()
    sclouds.sort()

    for idx, cloud in enumerate(sclouds):
        print "% 2s" % (1 + idx), cloud

    try:
        cloudidx = int(rlinput(
          "Please choose the cloud provider you want to setup [1-%d] " % 
            len(sclouds)))

        Cloud = get_cloud(sclouds[cloudidx - 1])
    except (IndexError, ValueError):
        return config(args)

    values = {}
    for what in Cloud.NEEDED_PARAMS:
        try:
            oldval = read_config()[CLOUDS_MAPPING[Cloud.PROVIDER_NAME]][what]
        except (IndexError, KeyError):
            oldval = ''
        values[what] = rlinput('Please provide your API %s: ' % what, oldval)

    if Cloud.test_conn(**values):
        write_config({ CLOUDS_MAPPING[Cloud.PROVIDER_NAME]: values })
        print Cloud.PROVIDER_NAME, "cloud configured properly" 
        return
    else:
        print "\nE: Invalid Credentials\n"
        return config(args)

def clouds(args):
    for cl in supported_clouds():
        print cl

def images(args):
    Cloud = get_cloud(args.cloudname)

    images = Cloud().list_images(keyword=args.keyword, limit=args.limit)

    print len(images), "images available on", Cloud.PROVIDER_NAME

    if not images:
        return

    table = Texttable()
    table.set_deco(Texttable.HEADER)
    rows = [ [ 'id', 'name', ] ]
    for img in images:
        rows.append([ img.id, img.name ])

    table.add_rows(rows)
    print table.draw()

def list_(args):
    Cloud = get_cloud(args.cloudname)

    nodes = Cloud().list_nodes()
    print len(nodes), "VMs running on", Cloud.PROVIDER_NAME

    if not nodes:
        return

    table = Texttable()
    table.set_deco(Texttable.HEADER)
    rows = [ [ 'id', 'name', 'state', 'ip' ] ]
    for node in nodes:
        rows.append([ node['id'], 
                      node['name'], 
                      node['state'], 
                      ', '.join(node['public_ips']) ])

    table.add_rows(rows)
    print table.draw()

def start(args):
    vm = get_cloud(args.cloudname)().deploy(args.imageid)
    print "Instance %s available on %s. Public IP: %s" % (
        vm['id'], args.cloudname, ', '.join(vm['public_ips']))

def reboot(args):
    print get_cloud(args.cloudname)().reboot(args.vmid)

def delete(args):
    print get_cloud(args.cloudname)().shutdown(args.vmid)

def main():
    arger = argparse.ArgumentParser(
        #usage='%(prog)s [options]',
        description='Start Virtual Machines on multiple clouds')

    subparsers = arger.add_subparsers()
    
    # config
    parser_config = subparsers.add_parser("config", help="set your cloud credentials")
    parser_config.set_defaults(func=config)

    # clouds
    parser_clouds = subparsers.add_parser("clouds", 
        help="list available clouds")
    parser_clouds.set_defaults(func=clouds)

    # list
    parser_list = subparsers.add_parser("list", help="list running VMs")
    parser_list.add_argument("cloudname", choices=supported_clouds())
    parser_list.set_defaults(func=list_)

    # images
    parser_images = subparsers.add_parser("images", 
        help="list available images")
    parser_images.add_argument("cloudname", choices=supported_clouds())
    parser_images.add_argument("--keyword", default='')
    parser_images.add_argument("--limit", default=0, type=int,
        help='the number of images to display')
    parser_images.set_defaults(func=images)
    
    # start
    parser_start = subparsers.add_parser("start", help="start a new VM")
    parser_start.add_argument("cloudname", choices=supported_clouds())
    parser_start.add_argument("imageid")
    parser_start.set_defaults(func=start)

    # reboot
    parser_reboot = subparsers.add_parser("reboot", help="reboot a given VM")
    parser_reboot.add_argument("cloudname", choices=supported_clouds())
    parser_reboot.add_argument("vmid")
    parser_reboot.set_defaults(func=reboot)

    # delete
    parser_delete = subparsers.add_parser("delete", help="delete a given VM")
    parser_delete.add_argument("cloudname", choices=supported_clouds())
    parser_delete.add_argument("vmid")
    parser_delete.set_defaults(func=delete)

    if len(sys.argv) == 1:
        # At least one argument is expected
        arger.print_help()
        return

    # We got (at least) one argument
    opts = arger.parse_args()
    opts.func(opts)

if __name__ == "__main__":
    main()
