#Django core bits
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext, loader, Context
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import Q
from django.contrib.sites.models import Site
from django.conf import settings
from django.http import HttpResponseRedirect, Http404, HttpResponse
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User, Group
from django.contrib import messages
from django.template.defaultfilters import slugify
from datetime import datetime, date, time
import csv
import pdfcrowd

from modules.core.decorators import *
from modules.core.functions import *
from modules.members.functions import *

#Forms
from forms import *
from modules.members.forms import *

#Models
from models import *
from modules.members.models import *
from modules.payments.models import *

from signals import *

#from modules.notifications import signals

@permission_required('admin_users.can_access_meeting_booking')
def meetings(request):

    enabled_meetings = Meeting.objects.filter(enabled=True).order_by('-start_date')
    disabled_meetings = Meeting.objects.filter(enabled=False).order_by('-start_date')

    return render_to_response('admin/meeting_booking/meetings.html',{'enabled_meetings':enabled_meetings,'disabled_meetings':disabled_meetings},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def add_meeting(request):

    form  = MeetingForm()

    if request.POST:
        form = MeetingForm(request.POST,request.FILES)
        if form.is_valid():
            try:
                meeting = form.save(commit=False)
                meeting.slug = slugify_unique(meeting.name,Meeting,'slug')
                meeting.save()
                messages.success(request,'Meeting Created')

            except:
                messages.error(request,'Could not add meeting')

            return HttpResponseRedirect(reverse('admin_meeting_booking'))

    return render_to_response('admin/meeting_booking/add-meeting.html',{'form':form},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def edit_meeting(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    form = MeetingForm(instance=meeting)

    if request.POST:
        form = MeetingForm(request.POST,request.FILES,instance=meeting)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Meeting Updated')
            except:
                messages.error(request,'Could not update meeting')

            return HttpResponseRedirect(reverse('admin_meeting_booking'))

    return render_to_response('admin/meeting_booking/edit-meeting.html',{'form':form,'meeting':meeting},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def delete_meeting(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    try:
        meeting.delete()
        messages.success(request,'Meeting Deleted')
    except:
        messages.error(request,'Could not delete meeting')

    return HttpResponseRedirect(reverse('admin_meeting_booking'))

@permission_required('admin_users.can_access_meeting_booking')
def enable_meeting(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    try:
        meeting.enabled=True
        meeting.save()
        messages.success(request,'Meeting has been enabled')
    except:
        messages.error(request,'Could not enable meeting')

    return HttpResponseRedirect(reverse('admin_meeting_booking'))


@permission_required('admin_users.can_access_meeting_booking')
def disable_meeting(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    try:
        meeting.enabled=False
        meeting.save()
        messages.success(request,'Meeting has been disabled')
    except:
        messages.error(request,'Could not enable meeting')

    return HttpResponseRedirect(reverse('admin_meeting_booking'))

@permission_required('admin_users.can_access_meeting_booking')
def update_confirmation_message(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    meeting_confirmation_form = MeetingConfirmationForm(instance=meeting)

    if request.POST:
        meeting_confirmation_form = MeetingConfirmationForm(request.POST,instance=meeting)

        if meeting_confirmation_form.is_valid():
            try:
                meeting_confirmation_form.save()
                messages.success(request,'Confirmation Message has been saved')

                return HttpResponseRedirect(reverse('admin_meeting_booking_update_confirmation_message',args=[meeting.id]))

            except:
                messages.error(request,'Could not save Confirmation Message')

    return render_to_response('admin/meeting_booking/update-confirmation-message.html',{'meeting':meeting,'meeting_confirmation_form':meeting_confirmation_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def duplicate_meeting(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    duplicate_form = MeetingDuplicateForm(instance=meeting)

    if request.POST:
        duplicate_form = MeetingDuplicateForm(request.POST)
        if duplicate_form.is_valid():

            try:
                new_meeting = duplicate_form.save(commit=False)
                new_meeting.slug = slugify_unique(new_meeting.name,Meeting,'slug')
                new_meeting.save()

                meeting_sessions = MeetingSession.objects.filter(meeting=meeting)
                for meeting_session in meeting_sessions:
                    new_meeting_session = copy_model_instance(meeting_session)
                    new_meeting_session.meeting = new_meeting
                    new_meeting_session.save()

                meeting_resources = MeetingResource.objects.filter(meeting=meeting)
                for meeting_resource in meeting_resources:
                    new_meeting_resource = copy_model_instance(meeting_resource)
                    new_meeting_resource.meeting = new_meeting
                    new_meeting_resource.save()

                messages.success(request,'Meeting Updated')
                return HttpResponseRedirect(reverse('admin_meeting_booking'))

            except:
                messages.error(request,'Could not save duplicate meeting')

    return render_to_response('admin/meeting_booking/duplicate-meeting.html',{'meeting':meeting,'form':duplicate_form},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def booking_types(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking_types = MeetingBookingType.objects.filter(meeting=meeting)

    return render_to_response('admin/meeting_booking/types/types.html',{'meeting':meeting,'booking_types':booking_types},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def add_booking_type(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    form = MeetingBookingTypeForm()

    if request.POST:
        form = MeetingBookingTypeForm(request.POST,request.FILES)

        if form.is_valid():
            try:
                booking_type = form.save(commit=False)
                booking_type.meeting = meeting
                booking_type.save()
                form.save_m2m()
                messages.success(request,'Booking Type')
            except:
                messages.error(request,'Could not create booking type')
            return HttpResponseRedirect(reverse('admin_meeting_booking_types',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/types/add-type.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_booking_type(request,meeting_id,type_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking_type = get_object_or_404(MeetingBookingType,id=type_id)

    form = MeetingBookingTypeForm(instance=booking_type)

    if request.POST:
        form = MeetingBookingTypeForm(request.POST,request.FILES,instance=booking_type)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Booking Type Updated')
            except:
                messages.error(request,'Could not update Booking Type')
            return HttpResponseRedirect(reverse('admin_meeting_booking_types',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/types/edit-type.html',{'meeting':meeting,'booking_type':booking_type,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def enable_booking_type(request,meeting_id,type_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking_type = get_object_or_404(MeetingBookingType,id=type_id)

    try:
        booking_type.enabled = True
        booking_type.save()
        messages.success(request,'Booking Type Enabled')
    except:
        messages.error(request,'Could not enable Booking Type')

    return HttpResponseRedirect(reverse('admin_meeting_booking_types',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def disable_booking_type(request,meeting_id,type_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking_type = get_object_or_404(MeetingBookingType,id=type_id)

    try:
        booking_type.enabled = False
        booking_type.save()
        messages.success(request,'Booking Type Disabled')
    except:
        messages.error(request,'Could not disable Booking Type')

    return HttpResponseRedirect(reverse('admin_meeting_booking_types',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def delete_booking_type(request,meeting_id,type_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking_type = get_object_or_404(MeetingBookingType,id=type_id)

    try:
        booking_type.delete()
        messages.success(request,'Booking Type Deleted')
    except:
        messages.error(request,'Could not delete Booking Type')

    return HttpResponseRedirect(reverse('admin_meeting_booking_types',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def sessions(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    session_categories = MeetingSessionCategory.objects.filter(meeting=meeting).order_by('order')

    return render_to_response('admin/meeting_booking/sessions/sessions.html',{'meeting':meeting,'session_categories':session_categories},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def add_session_category(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    form = MeetingSessionCategoryForm()

    if request.POST:
        form = MeetingSessionCategoryForm(request.POST)

        if form.is_valid():
            try:
                session_category = form.save(commit=False)
                session_category.meeting = meeting
                session_category.save()

                messages.success(request,'Session Category Created')

                return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))

            except:
                messages.error(request,'Could not create Session Category')

    return render_to_response('admin/meeting_booking/sessions/add-session-category.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def edit_session_category(request,meeting_id,category_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    category = get_object_or_404(MeetingSessionCategory,id=category_id)

    form = MeetingSessionCategoryForm(instance=category)

    if request.POST:
        form = MeetingSessionCategoryForm(request.POST,instance=category)

        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Session Category Updated')

                return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))

            except:
                messages.error(request,'Could not update Session Category')

    return render_to_response('admin/meeting_booking/sessions/edit-session-category.html',{'meeting':meeting,'category':category,'form':form},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def delete_session_category(request,meeting_id,category_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    category = get_object_or_404(MeetingSessionCategory,id=category_id)

    try:
        category.delete()
        messages.success(request,'Session Category Deleted')

    except:
        messages.errror(request,'Could not delete Session Category')

    return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def add_session(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    form = MeetingSessionForm()
    form.fields['session_category'].queryset = MeetingSessionCategory.objects.filter(meeting=meeting)

    if request.POST:
        form = MeetingSessionForm(request.POST,request.FILES)
        form.fields['session_category'].queryset = MeetingSessionCategory.objects.filter(meeting=meeting)

        if form.is_valid():
            try:
                session = form.save(commit=False)
                session.meeting = meeting
                session.save()
                form.save_m2m()
                messages.success(request,'Session Created')
            except:
                messages.error(request,'Could not create session')
            return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/sessions/add-session.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_session(request,meeting_id,session_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    session = get_object_or_404(MeetingSession,id=session_id)

    form = MeetingSessionForm(instance=session)
    form.fields['session_category'].queryset = MeetingSessionCategory.objects.filter(meeting=meeting)

    if request.POST:
        form = MeetingSessionForm(request.POST,request.FILES,instance=session)
        form.fields['session_category'].queryset = MeetingSessionCategory.objects.filter(meeting=meeting)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Session Updated')

                return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))

            except:
                messages.error(request,'Could not update session')

    return render_to_response('admin/meeting_booking/sessions/edit-session.html',{'meeting':meeting,'session':session,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def delete_session(request,meeting_id,session_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    session = get_object_or_404(MeetingSession,id=session_id)

    try:
        session.delete()
        messages.success(request,'Session Deleted')
    except:
        messages.error(request,'Could not delete session')

    return HttpResponseRedirect(reverse('admin_meeting_booking_sessions',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def session_bookings(request,meeting_id,session_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    session = get_object_or_404(MeetingSession,id=session_id)

    session_bookings = MeetingSessionBooking.objects.filter(session=session,waiting_list=False,meeting_booking__complete=True).exclude(meeting_booking__status='rejected').exclude(meeting_booking__status='cancelled').order_by('-meeting_booking__time')
    session_bookings_waiting = MeetingSessionBooking.objects.filter(session=session,waiting_list=True,meeting_booking__complete=True).order_by('-meeting_booking__time')

    return render_to_response('admin/meeting_booking/sessions/session-bookings.html',{'meeting':meeting,'session':session,'session_bookings':session_bookings,'session_bookings_waiting':session_bookings_waiting},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_meeting_booking')
def download_session_bookings(request,meeting_id,session_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    session = get_object_or_404(MeetingSession,id=session_id)

    session_bookings = MeetingSessionBooking.objects.filter(session=session,meeting_booking__complete=True).exclude(meeting_booking__status='rejected').exclude(meeting_booking__status='cancelled').order_by('-meeting_booking__time')

    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = "attachment; filename=session_bookings.csv"

    writer = csv.writer(response)

    writer.writerow(['Title','Given Name','Surname','Email Address','Created','Job Title','Address 1','Address 2','Town','Postcode','Country'])

    for session_booking in session_bookings:

        writer.writerow([unicode(s).encode("utf-8") for s in (session_booking.meeting_booking.title,session_booking.meeting_booking.given_name,session_booking.meeting_booking.surname,session_booking.meeting_booking.email_address,session_booking.meeting_booking.time.strftime('%H:%M %d /%m/%Y'),session_booking.meeting_booking.job_title,session_booking.meeting_booking.address_1,session_booking.meeting_booking.address_2,session_booking.meeting_booking.town,session_booking.meeting_booking.postcode,session_booking.meeting_booking.country)])

    return response


@permission_required('admin_users.can_access_meeting_booking')
def social_events(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    social_events = MeetingSocialEvent.objects.filter(meeting=meeting)

    return render_to_response('admin/meeting_booking/social_events/social-events.html',{'meeting':meeting,'social_events':social_events},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def add_social_event(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    form = MeetingSocialEventForm()

    if request.POST:
        form = MeetingSocialEventForm(request.POST,request.FILES)

        if form.is_valid():
            try:
                social_event = form.save(commit=False)
                social_event.meeting = meeting
                social_event.save()
                messages.success(request,'Social Event Created')

                return HttpResponseRedirect(reverse('admin_meeting_booking_social_events',args=[meeting.id]))
            except:
                messages.error(request,'Could not create Social Event')

    return render_to_response('admin/meeting_booking/social_events/add-social-event.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_social_event(request,meeting_id,event_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    social_event = get_object_or_404(MeetingSocialEvent,id=event_id)

    form = MeetingSocialEventForm(instance=social_event)

    if request.POST:
        form = MeetingSocialEventForm(request.POST,request.FILES,instance=social_event)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Social Event Updated')

                return HttpResponseRedirect(reverse('admin_meeting_booking_social_events',args=[meeting.id]))

            except:
                messages.error(request,'Could not update Social Event')

    return render_to_response('admin/meeting_booking/social_events/edit-social-event.html',{'meeting':meeting,'social_event':social_event,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def delete_social_event(request,meeting_id,event_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    social_event = get_object_or_404(MeetingSocialEvent,id=event_id)

    try:
        social_event.delete()
        messages.success(request,'Social Event Deleted')
    except:
        messages.error(request,'Could not delete Social Event')

    return HttpResponseRedirect(reverse('admin_meeting_booking_social_events',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def days(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    days = MeetingDay.objects.filter(meeting=meeting).order_by('order')

    return render_to_response('admin/meeting_booking/days/meeting-days.html',{'meeting':meeting,'days':days},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def add_day(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    form = MeetingDayForm()

    if request.POST:
        form = MeetingDayForm(request.POST,request.FILES)

        if form.is_valid():
            try:
                day = form.save(commit=False)
                day.meeting = meeting
                day.save()
                messages.success(request,'Meeting Day Created')
            except:
                messages.error(request,'Could not create Meeting Day')
            return HttpResponseRedirect(reverse('admin_meeting_booking_days',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/days/add-meeting-day.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_day(request,meeting_id,day_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    day = get_object_or_404(MeetingDay,id=day_id)

    form = MeetingDayForm(instance=day)

    if request.POST:
        form = MeetingDayForm(request.POST,request.FILES,instance=day)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Day Updated')
            except:
                messages.error(request,'Could not update Day')
            return HttpResponseRedirect(reverse('admin_meeting_booking_days',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/days/edit-meeting-day.html',{'meeting':meeting,'day':day,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def delete_day(request,meeting_id,day_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    day = get_object_or_404(MeetingDay,id=day_id)

    try:
        day.delete()
        messages.success(request,'Day Deleted')
    except:
        messages.error(request,'Could not delete Day')

    return HttpResponseRedirect(reverse('admin_meeting_booking_days',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def resources(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    resources = MeetingResource.objects.filter(meeting=meeting)

    return render_to_response('admin/meeting_booking/resources/meeting-resources.html',{'meeting':meeting,'resources':resources},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def add_resource(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    form = MeetingResourceForm()

    if request.POST:
        form = MeetingResourceForm(request.POST,request.FILES)

        if form.is_valid():
            try:
                resource = form.save(commit=False)
                resource.meeting = meeting
                resource.save()
                messages.success(request,'Resource Created')
            except:
                messages.error(request,'Could not create resource')
            return HttpResponseRedirect(reverse('admin_meeting_resources',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/resources/add-meeting-resource.html',{'meeting':meeting,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_resource(request,meeting_id,resource_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    resource = get_object_or_404(MeetingResource,id=resource_id)

    form = MeetingResourceForm(instance=resource)

    if request.POST:
        form = MeetingResourceForm(request.POST,request.FILES,instance=resource)
        if form.is_valid():
            try:
                resource.save()
                messages.success(request,'Resource Updated')
            except:
                messages.error(request,'Could not update resource')
        return HttpResponseRedirect(reverse('admin_meeting_resources',args=[meeting.id]))

    return render_to_response('admin/meeting_booking/edit-meeting-resource.html',{'meeting':meeting,'resource':resource,'form':form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def delete_resource(request,meeting_id,resource_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    resource = get_object_or_404(MeetingResource,id=resource_id)

    try:
        resource.delete()
        messages.success(request,'Resource Deleted')
    except:
        messages.error(request,'Could not delete resource')

    return HttpResponseRedirect(reverse('admin_meeting_resources',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def bookings(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    pending_bookings = MeetingBooking.objects.filter(meeting=meeting,status='pending',complete=True,invoiced=False).order_by('surname')
    invoiced_bookings = MeetingBooking.objects.filter(meeting=meeting,status='pending',complete=True,invoiced=True,paid=False).order_by('surname')
    approved_bookings = MeetingBooking.objects.filter(meeting=meeting,status='approved',complete=True).order_by('surname')

    rejected_bookings = MeetingBooking.objects.filter(meeting=meeting,status='rejected',complete=True).order_by('surname')
    cancelled_bookings = MeetingBooking.objects.filter(meeting=meeting,status='cancelled',complete=True).order_by('surname')
    incomplete_bookings = MeetingBooking.objects.filter(meeting=meeting,complete=False).order_by('surname')

    return render_to_response('admin/meeting_booking/bookings/bookings.html',{'meeting':meeting,'pending_bookings':pending_bookings,'invoiced_bookings':invoiced_bookings,'approved_bookings':approved_bookings,'rejected_bookings':rejected_bookings,'cancelled_bookings':cancelled_bookings,'incomplete_bookings':incomplete_bookings},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def new_booking(request,meeting_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)

    booking_form = MeetingBookingFormAdmin()
    booking_form.fields['type'].queryset = MeetingBookingType.objects.filter(meeting=meeting)
    address_form = MeetingBookingAddressFormAdmin()
    payment_form = MeetingBookingPaymentFormAdmin()
    notes_form  = MeetingBookingNotesFormAdmin()

    meeting_days = MeetingDay.objects.filter(meeting=meeting).order_by('order')
    sessions = MeetingSession.objects.filter(meeting=meeting).order_by('order')
    social_events = MeetingSocialEvent.objects.filter(meeting=meeting).order_by('order')

    errors = False

    if request.POST:
        booking_form = MeetingBookingFormAdmin(request.POST)
        address_form = MeetingBookingAddressFormAdmin(request.POST)
        payment_form = MeetingBookingPaymentFormAdmin(request.POST)
        notes_form  = MeetingBookingNotesFormAdmin(request.POST)

        if booking_form.is_valid() and address_form.is_valid() and payment_form.is_valid() and notes_form.is_valid():
            try:
                meeting_booking = MeetingBooking.objects.get(meeting=meeting,email_address=request.POST['email_address'],complete=True)
                messages.error(request,'Sorry, a booking already exists under this email address.')
                errors = True
            except MeetingBooking.DoesNotExist:
                pass

            try:
                meeting_booking = MeetingBooking.objects.get(meeting=meeting,email_address=request.POST['email_address'],complete=False)
                meeting_booking.delete()
            except:
                pass

            if not errors:

                meeting_booking = booking_form.save(commit=False)
                meeting_booking.unique_key = random_string_unique(100,MeetingBooking,'unique_key')
                meeting_booking.meeting = meeting
                booking_type = meeting_booking.type
                meeting_booking.type_name = booking_type.name
                meeting_booking.type_price = booking_type.cost
                meeting_booking.save()

                address_form = MeetingBookingAddressFormAdmin(request.POST,instance=meeting_booking)
                address_form.save()

                payment_form = MeetingBookingPaymentFormAdmin(request.POST,instance=meeting_booking)
                payment_form.save()

                notes_form = MeetingBookingNotesFormAdmin(request.POST,instance=meeting_booking)
                notes_form.save()

                posted_sessions = request.POST.getlist('sessions')
                posted_waiting = request.POST.getlist('waiting_list')
                posted_social_events = request.POST.getlist('social_events')

                errors = False

                try:
                    booking_member = Member.objects.get(user__email=meeting_booking.email_address)
                except:
                    booking_member = False

                if booking_member:
                    meeting_booking.member = booking_member
                    meeting_booking.registrant_type = booking_member.user_type
                    meeting_booking.job_title = booking_member.job_title
                    meeting_booking.hospital = booking_member.hospital
                    meeting_booking.address_1 = booking_member.address_1
                    meeting_booking.address_2 = booking_member.address_2
                    meeting_booking.town = booking_member.town
                    meeting_booking.county = booking_member.county
                    meeting_booking.country = booking_member.country
                    meeting_booking.postcode = booking_member.postcode
                    meeting_booking.telephone = booking_member.telephone

                    meeting_booking.save()

                else:

                    #new delegate
                    new_user = False
                    try:
                        user = User.objects.get(email=meeting_booking.email_address)
                    except User.DoesNotExist:
                        user = User(email=meeting_booking.email_address,first_name=meeting_booking.given_name,last_name=meeting_booking.surname)
                        user.username = random_string_unique(20,User,'username')
                        password = generate_random_password(10)
                        user.set_password(password)
                        user.save()
                        new_user = True

                    delegate = Member(user=user,user_type='non-member',given_name = meeting_booking.given_name,surname=meeting_booking.surname,title=meeting_booking.title)
                    if new_user:
                        delegate.raw_password = password
                    delegate.membership_number = get_next_membership_number()
                    delegate.save()

                    meeting_booking.member = delegate
                    meeting_booking.registrant_type = 'delegate'
                    meeting_booking.user_registered = new_user
                    meeting_booking.save()


                if request.POST.getlist('meeting_days'):
                    posted_days = request.POST.getlist('meeting_days')

                    for day_id in posted_days:
                        try:
                            meeting_day = MeetingDay.objects.get(id=day_id)
                            if meeting_booking.registrant_type == 'member':
                                amount_paid = meeting_day.get_member_cost()
                            else :
                                amount_paid = meeting_day.get_cost()
                            meeting_day_booking = MeetingDayBooking(meeting_booking=meeting_booking,meeting_day=meeting_day,meeting_day_name=meeting_day.name,price_paid=amount_paid)
                            meeting_day_booking.save()
                        except:
                            errors = True

                for session_id in posted_sessions:
                    try:
                        session = MeetingSession.objects.get(id=session_id)
                        try:
                            session_booking = MeetingSessionBooking.objects.get(meeting_booking=meeting_booking,session=session)
                        except MeetingSessionBooking.DoesNotExist:
                            session_booking = MeetingSessionBooking(meeting_booking=meeting_booking,session=session,session_name=session.name)
                            session_booking.save()
                    except:
                        errors = True

                for posted_waiting_id in posted_waiting:
                    try:
                        session = MeetingSession.objects.get(id=posted_waiting_id)
                        try:
                            session_booking = MeetingSessionBooking.objects.get(meeting_booking=meeting_booking,session=session)
                        except MeetingSessionBooking.DoesNotExist:
                            session_booking = MeetingSessionBooking(meeting_booking=meeting_booking,session=session,session_name=session.name,waiting_list=True)
                            session_booking.save()
                    except:
                        errors = True

                for social_event_id in posted_social_events:

                    try:
                        social_event = MeetingSocialEvent.objects.get(id=social_event_id)
                        quantity = request.POST.get("social_event_quantity_%s" % (social_event.id))

                        if quantity:
                            social_event_booking = MeetingSocialEventBooking(meeting_booking=meeting_booking,social_event=social_event,social_event_name=social_event.name,quantity=quantity,price_paid=social_event.cost)
                            social_event_booking.save()

                    except MeetingSocialEvent.DoesNotExist:
                        pass

                #last step
                meeting_booking.complete = True
                meeting_booking.status = 'approved'
                meeting_booking.save()

                if meeting_booking.paid:

                    if meeting_booking.price_paid > 0:
                        receipt_name = '%s' % (meeting)
                        receipt = Receipt(member=meeting_booking.member,meeting_booking=meeting_booking,type='meeting-booking',name=receipt_name,amount_paid=meeting_booking.price_paid,payment_type=meeting_booking.payment_method)
                        receipt.unique_key = random_string_unique(20,Receipt,'unique_key')
                        receipt.save()

                        #try:
                        # create an API client instance
                        client = pdfcrowd.Client("calmdigital", "dc33e7c4525620565185d0a00d90b8f0")
                        client.setPageMargins('50','50','0','50')
                        client.setFooterHtml('<p style="font-size:12px; text-align:center;">The Society for Vascular Technology of Great Britain and Ireland %s</p>' % (date.today().strftime('%d/%m/%Y')))

                        # convert an HTML string and save the result to a file
                        output_file = open(os.path.join(settings.MEDIA_ROOT, 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)), 'wb')

                        html = loader.render_to_string('members/receipts/view-receipt-pdf.html',{'receipt':receipt},context_instance=RequestContext(request))
                        client.convertHtml(html,output_file)

                        output_file.close()
                        #except:
                        #    pass

                        receipt.file = 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)
                        receipt.save()

                    else:
                        receipt = False

                    meeting_booking_confirmation_email.send(sender=None, meeting_booking=meeting_booking,receipt=receipt,email_admin=False)

                messages.success(request,'Meeting booking has been created')
                return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

        else:
            messages.error(request,'Could not create the meeting booking, please try again.')

    return render_to_response('admin/meeting_booking/bookings/new-booking.html',{'meeting':meeting,'booking_form':booking_form,'address_form':address_form,'payment_form':payment_form,'notes_form':notes_form,'meeting_days':meeting_days,'sessions':sessions,'social_events':social_events},context_instance=RequestContext(request))



@permission_required('admin_users.can_access_meeting_booking')
def view_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    meeting_booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    return render_to_response('admin/meeting_booking/bookings/view-booking.html',{'meeting':meeting,'meeting_booking':meeting_booking},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def edit_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    meeting_booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    booking_form = MeetingBookingFormEdit(instance=meeting_booking)
    address_form = MeetingBookingAddressFormAdmin(instance=meeting_booking)
    notes_form = MeetingBookingNotesFormAdmin(instance=meeting_booking)

    meeting_days = MeetingDay.objects.filter(meeting=meeting).order_by('order')
    meeting_days_booked = MeetingDayBooking.objects.filter(meeting_booking=meeting_booking)
    sessions = MeetingSession.objects.filter(meeting=meeting).order_by('order')
    sessions_booked = MeetingSessionBooking.objects.filter(meeting_booking=meeting_booking)
    social_events = MeetingSocialEvent.objects.filter(meeting=meeting).order_by('order')
    social_events_booked = MeetingSocialEventBooking.objects.filter(meeting_booking=meeting_booking)

    if request.POST:

        booking_form = MeetingBookingFormEdit(request.POST,instance=meeting_booking)
        address_form = MeetingBookingAddressFormAdmin(request.POST,instance=meeting_booking)
        notes_form = MeetingBookingNotesFormAdmin(request.POST,instance=meeting_booking)

        if booking_form.is_valid() and address_form.is_valid() and notes_form.is_valid():

            booking_form.save()

            for meeting_day_booked in meeting_days_booked:
                meeting_day_booked.delete()

            for session_booked in sessions_booked:
                session_booked.delete()

            for social_event_booked in social_events_booked:
                social_event_booked.delete()

            posted_sessions = request.POST.getlist('sessions')
            posted_waiting = request.POST.getlist('waiting_list')
            posted_social_events = request.POST.getlist('social_events')

            errors = False

            if request.POST.getlist('meeting_days'):
                posted_days = request.POST.getlist('meeting_days')

                for day_id in posted_days:
                    try:
                        meeting_day = MeetingDay.objects.get(id=day_id)
                        if meeting_booking.registrant_type == 'member':
                            amount_paid = meeting_day.get_member_cost(meeting_booking.time.date())
                        else :
                            amount_paid = meeting_day.get_cost(meeting_booking.time.date())
                        meeting_day_booking = MeetingDayBooking(meeting_booking=meeting_booking,meeting_day=meeting_day,meeting_day_name=meeting_day.name,price_paid=amount_paid)
                        meeting_day_booking.save()
                    except:
                        errors = True

            for session_id in posted_sessions:
                try:
                    session = MeetingSession.objects.get(id=session_id)
                    try:
                        session_booking = MeetingSessionBooking.objects.get(meeting_booking=meeting_booking,session=session)
                    except MeetingSessionBooking.DoesNotExist:
                        session_booking = MeetingSessionBooking(meeting_booking=meeting_booking,session=session,session_name=session.name)
                        session_booking.save()
                except:
                    errors = True

            for posted_waiting_id in posted_waiting:
                try:
                    session = MeetingSession.objects.get(id=posted_waiting_id)
                    try:
                        session_booking = MeetingSessionBooking.objects.get(meeting_booking=meeting_booking,session=session)
                    except MeetingSessionBooking.DoesNotExist:
                        session_booking = MeetingSessionBooking(meeting_booking=meeting_booking,session=session,session_name=session.name,waiting_list=True)
                        session_booking.save()
                except:
                    errors = True

            if posted_social_events:

                for social_event_id in posted_social_events:

                    try:
                        social_event = MeetingSocialEvent.objects.get(id=social_event_id)
                        quantity = request.POST.get("social_event_quantity_%s" % (social_event.id))

                        if quantity:
                            social_event_booking = MeetingSocialEventBooking(meeting_booking=meeting_booking,social_event=social_event,social_event_name=social_event.name,quantity=quantity,price_paid=social_event.cost)
                            social_event_booking.save()

                    except MeetingSocialEvent.DoesNotExist:
                        pass

            messages.success(request,'Meeting booking has been updated')
            return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

        else:
            messages.error(request,'Could not update the meeting booking, please try again.')

    return render_to_response('admin/meeting_booking/bookings/edit-booking.html',{'meeting':meeting,'meeting_booking':meeting_booking,'booking_form':booking_form,'address_form':address_form,'notes_form':notes_form,'meeting_days':meeting_days,'meeting_days_booked':meeting_days_booked,'sessions':sessions,'sessions_booked':sessions_booked,'social_events':social_events,'social_events_booked':social_events_booked},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_meeting_booking')
def approve_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    #try:
    booking.status = 'approved'
    booking.save()

    member = booking.member

    if booking.member:
        user_activity = UserActivity(member=member,title="Meeting Booking Approved",text='Your booking for meeting %s has been approved. <a href="%s">View the details of your booking.</a>.' % (meeting,reverse('account_view_meeting_booking',args=[booking.id])), type='meeting-notification')
        user_activity.save()

    #if booking.user_registered:
    #    member.approved = True
    #    member.complete = True
    #    member.save()
    #meeting_booking_approved_account.send(sender=None, request=request, meeting_booking=booking)

    #meeting_booking_approved.send(sender=None, request=request, meeting_booking=booking)

    messages.success(request,'Booking has been approved')
    #except:
    #    messages.error(request,'Could not update booking')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def cancel_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    booking.status = 'cancelled'
    booking.save()

    messages.success(request,'Booking has been cancelled')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def invoice_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    booking.invoiced = True
    booking.save()

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def mark_paid_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    meeting_booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    #try:
    meeting_booking.paid = True
    meeting_booking.price_paid = meeting_booking.get_total()
    meeting_booking.save()

    if meeting_booking.member:
        receipt_name = '%s' % (meeting)
        receipt = Receipt(member=meeting_booking.member,meeting_booking=meeting_booking,type='meeting-booking',name=receipt_name,amount_paid=meeting_booking.get_total(),payment_type='Invoice')
        receipt.unique_key = random_string_unique(20,Receipt,'unique_key')
        receipt.save()

        #try:
        # create an API client instance
        client = pdfcrowd.Client("calmdigital", "dc33e7c4525620565185d0a00d90b8f0")
        client.setPageMargins('50','50','0','50')
        client.setFooterHtml('<p style="font-size:12px; text-align:center;">The Society for Vascular Technology of Great Britain and Ireland %s</p>' % (date.today().strftime('%d/%m/%Y')))

        # convert an HTML string and save the result to a file
        output_file = open(os.path.join(settings.MEDIA_ROOT, 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)), 'wb')

        html = loader.render_to_string('members/receipts/view-receipt-pdf.html',{'receipt':receipt},context_instance=RequestContext(request))
        client.convertHtml(html,output_file)

        output_file.close()
        #except:
        #    pass

        receipt.file = 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)
        receipt.save()

        #send notification
        meeting_booking_invoice_paid.send(sender=None,request=request,meeting_booking=meeting_booking,receipt=receipt)

    meeting_booking.status = 'approved'
    meeting_booking.save()

    if meeting_booking.member:
        user_activity = UserActivity(member=meeting_booking.member,title="Meeting Booking Approved",text='Your booking for meeting %s has been approved. <a href="%s">View the details of your booking.</a>.' % (meeting,reverse('account_view_meeting_booking',args=[meeting_booking.id])), type='meeting-notification')
        user_activity.save()

    messages.success(request,'Booking marked as paid')

    #except:
    #    messages.error(request,'Could not mark booking as paid')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))


@permission_required('admin_users.can_access_meeting_booking')
def reject_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    try:
        booking.status = 'rejected'
        booking.save()
        messages.success(request,'Booking has been rejected')
    except:
        messages.error(request,'Could not update booking')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def delete_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    #try:
    booking.delete()
    messages.success(request,'Booking has been deleted')
    #except:
    #   messages.error(request,'Could not delete booking')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))

@permission_required('admin_users.can_access_meeting_booking')
def resend_booking(request,meeting_id,booking_id):

    meeting = get_object_or_404(Meeting,id=meeting_id)
    meeting_booking = get_object_or_404(MeetingBooking,id=booking_id,meeting=meeting)

    if meeting_booking.price_paid > 0:
        receipt_name = '%s' % (meeting)
        receipt = Receipt(member=meeting_booking.member,meeting_booking=meeting_booking,type='meeting-booking',name=receipt_name,amount_paid=meeting_booking.price_paid)
        receipt.payment_type=meeting_booking.payment_method
        receipt.unique_key = random_string_unique(20,Receipt,'unique_key')
        receipt.save()

        #try:
        # create an API client instance
        client = pdfcrowd.Client("calmdigital", "dc33e7c4525620565185d0a00d90b8f0")
        client.setPageMargins('50','50','0','50')
        client.setFooterHtml('<p style="font-size:12px; text-align:center;">The Society for Vascular Technology of Great Britain and Ireland %s</p>' % (date.today().strftime('%d/%m/%Y')))

        # convert an HTML string and save the result to a file
        output_file = open(os.path.join(settings.MEDIA_ROOT, 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)), 'wb')

        html = loader.render_to_string('members/receipts/view-receipt-pdf.html',{'receipt':receipt},context_instance=RequestContext(request))
        client.convertHtml(html,output_file)

        output_file.close()
        #except:
        #    pass

        receipt.file = 'members/receipts/meeting_booking_%s.pdf' % (receipt.id)
        receipt.save()

    else:
        receipt = False

    meeting_booking_confirmation_email.send(sender=None, meeting_booking=meeting_booking,receipt=receipt,email_admin=False)

    messages.success(request,'Email has been resent')

    return HttpResponseRedirect(reverse('admin_meeting_booking_bookings',args=[meeting.id]))
