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

# Copyright 2012 Openstack, LLC
#
#    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
import tempfile
import zipfile
from contextlib import closing

from django import http
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _

from horizon import api
from horizon import exceptions
from horizon import forms


LOG = logging.getLogger(__name__)


class DownloadX509Credentials(forms.SelfHandlingForm):
    tenant = forms.ChoiceField(label=_("Select a Project"))

    # forms.SelfHandlingForm doesn't pass request object as the first argument
    # to the class __init__ method, which causes form to explode.
    @classmethod
    def _instantiate(cls, request, *args, **kwargs):
        return cls(request, *args, **kwargs)

    def __init__(self, request, *args, **kwargs):
        super(DownloadX509Credentials, self).__init__(*args, **kwargs)
        # Populate tenant choices
        tenant_choices = []
        try:
            tenant_list = api.keystone.tenant_list(request)
        except:
            tenant_list = []
            exceptions.handle(request, _("Unable to retrieve tenant list."))

        for tenant in tenant_list:
            if tenant.enabled:
                tenant_choices.append((tenant.id, tenant.name))
        if not tenant_choices:
            self.fields['tenant'].choices = ('', 'No Available Tenants')
        else:
            self.fields['tenant'].choices = tenant_choices

    def handle(self, request, data):
        def find_or_create_access_keys(request, tenant_id):
            keys = api.keystone.list_ec2_credentials(request, request.user.id)
            if keys:
                #TODO(jakedahn): Once real CRUD is created, we can allow user
                #                to generate per access/secret pair.
                return keys[0]
            else:
                return api.keystone.create_ec2_credentials(request,
                                                           request.user.id,
                                                           tenant_id)
        try:
            # NOTE(jakedahn): Keystone errors unless we specifically scope
            #                 the token to tenant before making the call.
            api.keystone.token_create_scoped(request,
                                             data.get('tenant'),
                                             request.user.token)
            credentials = api.nova.get_x509_credentials(request)
            cacert = api.nova.get_x509_root_certificate(request)
            keys = find_or_create_access_keys(request, data.get('tenant'))
            context = {'ec2_access_key': keys.access,
                       'ec2_secret_key': keys.secret,
                       'ec2_endpoint': api.url_for(request,
                                                   'ec2',
                                                   endpoint_type='publicURL')}
            try:
                s3_endpoint = api.url_for(request,
                                          's3',
                                          endpoint_type='publicURL')
            except exceptions.ServiceCatalogException:
                s3_endpoint = None
            context['s3_endpoint'] = s3_endpoint
        except:
            exceptions.handle(request,
                              _('Unable to fetch EC2 credentials.'),
                              redirect=request.build_absolute_uri())

        try:
            temp_zip = tempfile.NamedTemporaryFile(delete=True)
            with closing(zipfile.ZipFile(temp_zip.name, mode='w')) as archive:
                archive.writestr('pk.pem', credentials.private_key)
                archive.writestr('cert.pem', credentials.data)
                archive.writestr('cacert.pem', cacert.data)
                archive.writestr('ec2rc.sh', render_to_string(
                                 'settings/ec2/ec2rc.sh.template', context))
        except:
            exceptions.handle(request,
                              _('Error writing zipfile: %(exc)s'),
                              redirect=request.build_absolute_uri())

        response = http.HttpResponse(mimetype='application/zip')
        response.write(temp_zip.read())
        response['Content-Disposition'] = 'attachment; \
                                           filename=%s-x509.zip' \
                                           % data.get('tenant')
        response['Content-Length'] = temp_zip.tell()
        return response
