#!/usr/bin/env python
#######################################################################
# Copyright (c) 2013 Adam Wisniewski, http://adamw523.com
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import getopt
import inspect
import os
import sys

import dodo

OUTPUT_COLUMNS = {  'regions':  [['id', 5], ['name', 30]],
                    'sizes':    [['id', 5], ['size', 30]],
                    'images':   [['id', 8], ['distribution', 20], ['name', 30]],
                    'ssh_keys': [['id', 7], ['name', 40]],
                    'droplets': [['id', 9], ['name', 40], ['image_id', 5],
                                 ['region_id', 6], ['size_id', 4], ['status', 10],
                                 ['backups_active', 7]]
        }

OPTIONS = ['droplet_id=', 'filter=', 'image_id=', 'name=', 'region_id=',
            'size_id=', 'ssh_key_ids=', 'ssh_key_pub=', 'new',
            'destroy', 'show', 'reboot', 'power_cycle', 'shutdown',
            'power_off', 'power_on', 'reset_root_password', 'resize',
            'snapshot', 'restore', 'rebuild', 'enable_backups',
            'disable_backups', 'ssh_key_id=', 'help']

def usage_options(lead=18):
    out = ''
    o = ['[--' + o.translate(None, '=') + ']' for o in sorted(OPTIONS)]
    for i in xrange(0, len(o), 4):
        if i > 0: out += ' ' * lead
        out += ' '.join(o[i:i + 4])
        out += '\n'
    return out

def usage():
    out = 'Usage: dodo resource '
    out += usage_options(lead=21)
    print out

def usage_long():
    out = '''NAME
    dodo - A DigitalOcean command line interface

SYNOPSIS
    dodo resource '''

    out += usage_options()

    out += '''OPTIONS
    resource
        droplets, images, regions, sizes, ssh_keys

    --filter
        my_images, global

FILES
    ~/.dodo
        Credentials configuration file:

        Example:

        [crednetials]
        client=<client_key>
        api=<api_key>
    '''

    print out

def print_list(list_type, items):
    """
    Print out a list of dict in a table format. The formats are defined
    in OUTPUT_COLUMNS and specified with the list_type parameter.
    """
    columns = OUTPUT_COLUMNS[list_type]
    row_len = sum([c[1] + 1 for c in columns])

    # print column headers
    for column in columns:
        print column[0][:column[1]].ljust(column[1]),
    print

    # print divider
    print '-' * row_len

    # print list items
    for row in items:
        for column in columns:
            # print row, column[0]
            value = str(row[column[0]])
            print value[:column[1] - 1].ljust(column[1]),

        print

def print_dict(out_dict):
    """
    Print out a dict in 2 column format
    """
    for k in out_dict:
        print k[:15].ljust(15),
        print ': ',
        print out_dict[k]


########################################
# Commands

def droplets(opts):
    conn = dodo.connect()
    if 'new' in opts:
        # creating a new droplet
        if 'ssh_key_ids' in opts:
            ssh_key_ids = opts['ssh_key_ids']
        else:
            ssh_key_ids = None

        droplet = conn.new_droplet(opts['name'], opts['size_id'],
                opts['image_id'],
                opts['region_id'], ssh_key_ids)

        print_dict(droplet)

    elif 'destroy' in opts:
        res = conn.destroy_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'disable_backups' in opts:
        res = conn.disable_backups_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'enable_backups' in opts:
        res = conn.enable_backups_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'power_cycle' in opts:
        res = conn.power_cycle_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'power_off' in opts:
        res = conn.power_off_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'power_on' in opts:
        res = conn.power_on_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'reboot' in opts:
        res = conn.reboot_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'reset_root_password' in opts:
        res = conn.reset_root_password_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'rebuild' in opts:
        res = conn.rebuild_droplet(opts['droplet_id'], opts['image_id'])
        print_dict(res)

    elif 'resize' in opts:
        res = conn.resize_droplet(opts['droplet_id'], opts['size_id'])
        print_dict(res)

    elif 'restore' in opts:
        res = conn.restore_droplet(opts['droplet_id'], opts['image_id'])
        print_dict(res)

    elif 'show' in opts:
        res = conn.show_droplet(opts['droplet_id'])
        print_dict(res)

    elif 'snapshot' in opts:
        name = opts.get('name', None)
        res = conn.snapshot_droplet(opts['droplet_id'], name)
        print_dict(res)

    elif 'shutdown' in opts:
        res = conn.shutdown_droplet(opts['droplet_id'])
        print_dict(res)

    else:
        droplets = conn.droplets()
        print_list('droplets', droplets)

def images(opts):
    conn = dodo.connect()

    if 'destroy' in opts:
        res = conn.destroy_image(opts['image_id'])
        print_dict(res)

    elif 'show' in opts:
        image = conn.show_image(opts['image_id'])
        print_dict(image)

    else:
        if 'filter' in opts:
            images = conn.images(opts['filter'])
        else:
            images = conn.images()
        print_list('images', images)

def regions(opts):
    conn = dodo.connect()
    regions = conn.regions()
    print_list('regions', regions)

def ssh_keys(opts):
    conn = dodo.connect()
    if 'show' in opts:
        ssh_key = conn.ssh_key(opts['ssh_key_id'])
        print_dict(ssh_key)
    else:
        ssh_keys = conn.ssh_keys()
        print_list('ssh_keys', ssh_keys)

def sizes(opts):
    conn = dodo.connect()
    regions = conn.sizes()
    print_list('regions', regions)

########################################
# main

def main():
    if len(sys.argv) == 2 and sys.argv[1] == '--help':
        usage_long()
        sys.exit()

    try:
        resource = sys.argv[1]
        argv = sys.argv[2:]
        opts, args = getopt.getopt(argv, '', OPTIONS)
        opts = dict(((opt[0][2:], opt[1]) for opt in opts))
    except Exception as e:
        usage()
        sys.exit(2)

    if not hasattr(dodo.config, 'client_id'):
        print 'ERROR: dodo configuration not found. Run `dodo --help` for ',
        print 'more info.'
        print
        sys.exit(2)
    else:
        try:
            if resource == 'droplets': droplets(opts)
            elif resource == 'images': images(opts)
            elif resource == 'regions': regions(opts)
            elif resource == 'ssh_keys': ssh_keys(opts)
            elif resource == 'sizes': sizes(opts)
            else: usage()
        except KeyError as e:
            print "Cannot find value: " + str(e)

if __name__ == "__main__":
    main()
