# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2011 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2011 Fourth Paradigm Development, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import logging

from django import template
from django.conf.urls.defaults import *
from django.contrib import messages
from django.shortcuts import redirect
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required

from glance.common import exception as glance_exception

from openstack_dashboard import api
from openstack_dashboard import forms
from openstack_dashboard.plugins import get_topbar_name


topbar = get_topbar_name(__file__)
INSTANCES = r'^instances/(?P<instance_id>[^/]+)/%s$'
IMAGES = r'^images/(?P<image_id>[^/]+)/%s$'
urlpatterns = patterns(__name__,
    url(r'^images/$', 'index', name=topbar + '/images'),
    url(IMAGES % 'update', 'update', name=topbar + '/images_update'),
    #url(INSTANCES % 'vnc', 'vnc', name=topbar + '/instances_vnc'),
)

LOG = logging.getLogger(__name__)


class DeleteImage(forms.SelfHandlingForm):
    image_id = forms.CharField(required=True)

    def handle(self, request, data):
        image_id = data['image_id']
        try:
            api.image_delete(request, image_id)
        except glance_exception.ClientConnectionError, e:
            LOG.error("Error connecting to glance", exc_info=True)
            messages.error(request,
                           "Error connecting to glance: %s" % e.message)
        except glance_exception.Error, e:
            LOG.error('Error deleting image with id "%s"' % image_id,
                      exc_info=True)
            messages.error(request, "Error deleting image: %s" % e.message)
        return redirect(request.build_absolute_uri())


class ToggleImage(forms.SelfHandlingForm):
    image_id = forms.CharField(required=True)

    def handle(self, request, data):
        image_id = data['image_id']
        try:
            api.image_update(request, image_id, image_meta={'is_public': False})
        except glance_exception.ClientConnectionError, e:
            LOG.error("Error connecting to glance", exc_info=True)
            messages.error(request,
                           "Error connecting to glance: %s" % e.message)
        except glance_exception.Error, e:
            LOG.error('Error updating image with id "%s"' % image_id,
                      exc_info=True)
            messages.error(request, "Error updating image: %s" % e.message)
        return redirect(request.build_absolute_uri())

class UpdateImageForm(forms.SelfHandlingForm):
    name = forms.SlugField(max_length="25", label="Name")
    kernel = forms.IntegerField(label="Kernel ID", required=False)
    ramdisk = forms.IntegerField(label="Ramdisk ID", required=False)
    architecture = forms.CharField(label="Architecture", required=False)
    #project_id = forms.CharField(label="Project ID")
    container_format = forms.CharField(label="Container Format", required=False)
    disk_format = forms.CharField(label="Disk Format")
    #is_public = forms.BooleanField(label="Publicly Available", required=False)


@login_required
def index(request):
    for f in (DeleteImage, ToggleImage):
        _, handled = f.maybe_handle(request)
        if handled:
            return handled

    # We don't have any way of showing errors for these, so don't bother
    # trying to reuse the forms from above
    delete_form = DeleteImage()
    toggle_form = ToggleImage()

    images = []
    try:
        images = api.image_list_detailed(request)
        if not images:
            messages.info(request, "There are currently no images.")
    except glance_exception.ClientConnectionError, e:
        LOG.error("Error connecting to glance", exc_info=True)
        messages.error(request, "Error connecting to glance: %s" % e.message)
    except glance_exception.Error, e:
        LOG.error("Error retrieving image list", exc_info=True)
        messages.error(request, "Error retrieving image list: %s" % e.message)

    return render_to_response(topbar + '/image_view.html', {
        'delete_form': delete_form,
        'toggle_form': toggle_form,
        'images': images,
    }, context_instance = template.RequestContext(request))


@login_required
def update(request, image_id):
    try:
        image = api.image_get(request, image_id)
    except glance_exception.ClientConnectionError, e:
        LOG.error("Error connecting to glance", exc_info=True)
        messages.error(request, "Error connecting to glance: %s" % e.message)
    except glance_exception.Error, e:
        LOG.error('Error retrieving image with id "%s"' % image_id,
                  exc_info=True)
        messages.error(request,
                       "Error retrieving image %s: %s" % (image_id, e.message))

    if request.method == "POST":
        form = UpdateImageForm(request.POST)
        if form.is_valid():
            image_form = form.clean()
            metadata = {
                'is_public': True,
                'disk_format': image_form['disk_format'],
                'container_format': image_form['container_format'],
                'name': image_form['name'],
            }
            try:
                # TODO add public flag to properties
                metadata['properties'] = {}
                if image_form['kernel']:
                    metadata['properties']['kernel_id'] = image_form['kernel']
                if image_form['ramdisk']:
                    metadata['properties']['ramdisk_id'] = image_form['ramdisk']
                if image_form['architecture']:
                    metadata['properties']['architecture'] = image_form['architecture']
                api.image_update(request, image_id, metadata)
                messages.success(request, "Image was successfully updated.")
            except glance_exception.ClientConnectionError, e:
                LOG.error("Error connecting to glance", exc_info=True)
                messages.error(request,
                               "Error connecting to glance: %s" % e.message)
            except glance_exception.Error, e:
                LOG.error('Error updating image with id "%s"' % image_id,
                          exc_info=True)
                messages.error(request, "Error updating image: %s" % e.message)
            except:
                LOG.error('Unspecified Exception in image update',
                          exc_info=True)
                messages.error(request,
                               "Image could not be updated, please try again.")
            return redirect(topbar + "/images")
        else:
            LOG.error('Image "%s" failed to update' % image['name'],
                      exc_info=True)
            messages.error(request,
                           "Image could not be uploaded, please try agian.")
            form = UpdateImageForm(request.POST)
            return render_to_response(topbar + '/image_update.html',{
                'image': image,
                'form': form,
            }, context_instance = template.RequestContext(request))
    else:
        form = UpdateImageForm(initial={
                'name': image.get('name', ''),
                'kernel': image['properties'].get('kernel_id', ''),
                'ramdisk': image['properties'].get('ramdisk_id', ''),
                'is_public': image.get('is_public', ''),
                'location': image.get('location', ''),
                'state': image['properties'].get('image_state', ''),
                'architecture': image['properties'].get('architecture', ''),
                'project_id': image['properties'].get('project_id', ''),
                'container_format': image.get('container_format', ''),
                'disk_format': image.get('disk_format', ''),
            })

        return render_to_response(topbar + '/image_update.html',{
            'image': image,
            'form': form,
        }, context_instance = template.RequestContext(request))


@login_required
def upload(request):
    if request.method == "POST":
        form = UploadImageForm(request.POST)
        if form.is_valid():
            image = form.clean()
            metadata = {'is_public': image['is_public'],
                        'disk_format': 'ami',
                        'container_format': 'ami',
                        'name': image['name']}
            try:
                messages.success(request, "Image was successfully uploaded.")
            except:
                # TODO add better error management
                messages.error(request, "Image could not be uploaded, please try again.")

            try:
                api.image_create(request, metadata, image['image_file'])
            except glance_exception.ClientConnectionError, e:
                LOG.error('Error connecting to glance while trying to upload'
                          ' image', exc_info=True)
                messages.error(request,
                               "Error connecting to glance: %s" % e.message)
            except glance_exception.Error, e:
                LOG.error('Glance exception while uploading image',
                          exc_info=True)
                messages.error(request, "Error adding image: %s" % e.message)
        else:
            LOG.error('Image "%s" failed to upload' % image['name'],
                      exc_info=True)
            messages.error(request,
                           "Image could not be uploaded, please try agian.")
            form = UploadImageForm(request.POST)
            return render_to_response('django_nova_systopbar/images/image_upload.html',{
                'form': form,
            }, context_instance = template.RequestContext(request))

        return redirect(topbar + '/images')
    else:
        form = UploadImageForm()
        return render_to_response('django_nova_systopbar/images/image_upload.html',{
            'form': form,
        }, context_instance = template.RequestContext(request))
