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

from flask import Flask
from flask import request
from novaclient import exceptions
import json
import time

# our own module
from credentials import get_nova_client
from credentials import get_glance_client
from credentials import get_neutron_client

# our own module
from cloud_client.ret_code import cloud_client
from cloud_client.ret_code import general

# CloudClient base class
from cloud_client.client import CloudClient

'''import ret_code

app = Flask(__name__)

# launch an instance and return the instance id and allocated float ip address
def launch_instance():

    # do we miss any argument?
    # if do not do this
    # the server will simply throw a 400-error to the user
    # which is not so imformative
    if 'image' not in request.form or \
            'flavor' not in request.form or \
            'internet' not in request.form or \
            'name' not in request.form:
        return json.dumps(ret_code.err_arg_missed)

    nova = get_nova_client()

    # sanity check
    try:
        # print request.form['image']
        image = nova.images.find(id = request.form['image'])
    except exceptions.NotFound, msg:
        print msg
        return json.dumps(ret_code.err_inval_image)

    try:
        # print request.form['flavor']
        flavor = nova.flavors.find(id = request.form['flavor'])
    except exceptions.NotFound, msg:
        print msg
        return json.dumps(ret_code.err_inval_flavor)

    # all the instances will be attached to the network
    net_name = 'network_oj'
    try:
        net = nova.networks.find(label = net_name)
    except exceptions.NotFound, msg:
        print msg
        return json.dumps({'ret_code':ret_code.ERR_INVAL_CLOUD_CONFIG, 
        'description':msg.message})

    nics = [{'net-id': net.id}]

    internet = request.form['internet']
    if internet == 'true':
        security_groups = ['oj_teacher']
    elif internet == 'false':
        security_groups = ['oj_exam']
    else:
        return json.dumps(ret_code.err_inval_internet)

    try:
        server = nova.servers.create(request.form['name'], image = image, 
                flavor = flavor, security_groups = security_groups, 
                nics = nics)
    except exceptions.BadRequest, msg:
        # this may happed due to non-existence of the security_group
        print msg
        # msg is a BadRequest object, it is printable but not json serializable
        # so we need to use msg.message
        return json.dumps({'ret_code':ret_code.ERR_INVAL_CLOUD_CONFIG, 
            'description':msg.message})

    server_id = server.id

    # sleep for 5 seconds and see whether we can launch it
    for i in range(60):
        time.sleep(1)
        server = nova.servers.get(server_id)
        # this may encounter problems when the cloud is too slow
        # that it builds a image for more than 5 seconds and then failed
        # we may need to modify this to deal with this corner case
        if server.status == 'ERROR' or (i == 59 and server.status != 'ACTIVE'):
            print server_id, server.status
            nova.servers.delete(server)
            return json.dumps(ret_code.err_vm_creation_failure)
        elif server.status == 'ACTIVE':
            break
        else:
            pass

    # assign floating ips
    try:
        floating_ip = nova.floating_ips.create(pool = 'EXT_01')
    except exceptions.NotFound, msg:
        # EXT_01 does not exist!
        print msg
        # do not forget to release resources
        nova.servers.delete(server)
        return json.dumps({'ret_code':ret_code.ERR_INVAL_CLOUD_CONFIG, 'description':msg.message})

    server.add_floating_ip(address = floating_ip)

    return json.dumps({'ret_code':ret_code.RET_SUCCESS, 'description':'Success', 
        'vm_id':server_id, 'vm_ip':floating_ip.ip})

def terminate_instance():

    # check if any argument is missing
    if 'vm_id' not in request.form or \
            'floating_ip' not in request.form:
        return json.dumps(ret_code.err_arg_missed)

    nova = get_nova_client()

    # delete server according to virtual machine's ID
    vm_id = request.form['vm_id']
    try:
        server = nova.servers.get(vm_id)
        # Should add code to release floating IP
        floating_ip = request.form['floating_ip']
        floating_list = nova.floating_ips.list()
        for i in range(len(floating_list)):
            if floating_ip == floating_list[i].ip:
                floating_id = floating_list[i].id
        nova.floating_ips.delete(floating_id)
        nova.servers.delete(server)
        return json.dumps({'ret_code':ret_code.RET_SUCCESS, 'description':'Success'})
    except exceptions.NotFound, msg:
        print msg
        return json.dumps(ret_code.err_inval_vm_id)

def fetch_image_flavor():

    glance = get_glance_client()

    image = list(glance.images.list())

    nova = get_nova_client()

    flavor = nova.flavors.list()

    image_flavor_list = \
    {"image": [[i.id.encode('utf-8'), {'Name': i.name.encode('utf-8'), 'Status': i.status.encode('utf-8'), 'Visibility': i.visibility.encode('utf-8'), 'Protected': i.protected, 'Disk format': i.disk_format.encode('utf-8'), 'Size': i.size}] for i in image], \
     "flavor": [[i.id.encode('utf-8'), {'Name': i.name.encode('utf-8'), 'VCPUs': i.vcpus, 'RAM': i.ram, 'Root disk': i.disk, 'Is_public': i.is_public}] for i in flavor]
}

    return json.dumps(image_flavor_list)

def create_snapshot():

    # check if any argument is missing
    if 'server' not in request.form or \
            'name' not in request.form:
        return json.dumps(ret_code.err_arg_missed)

    nova = get_nova_client()

    server_id = request.form['server']
    try:
        server = nova.servers.get(server_id)
        name = request.form['name']
        nova.servers.create_image(server, name)
        return json.dumps({'ret_code':ret_code.RET_SUCCESS, 'description':'Success'})
    except exceptions.NotFound, msg:
        print msg
        return json.dumps(ret_code.err_inval_vm_id)

dispatch_table = {
        'launch_instance':launch_instance,
        'terminate_instance':terminate_instance,
        'fetch_image_flavor':fetch_image_flavor,
        'create_snapshot':create_snapshot
        }

@app.route('/cloud_api', methods=['POST'])
def dispatcher():
    # the user posted form is request.form
    print request.form
    if 'command' not in request.form:
        return json.dumps(ret_code.err_inval_cmd)

    command = request.form['command']
    if command not in dispatch_table:
        return json.dumps(ret_code.err_inval_cmd)
    else:
        return dispatch_table[command]()


if __name__ == '__main__':
    app.run(host = '0.0.0.0', port = 50000)'''



class OpenstackClient(CloudClient):
    def __init__(self):