from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponseNotFound
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required, user_passes_test
from django.conf import settings

from mailer.models import Message, DontSendEntry, MessageLog
from django.template import Context, Template

from models import Lead, CRMTag, Communication, Role, Language, EmailJob, LinkAddress
from django.conf import settings
from django.template import RequestContext

from utils import update_email_response

staff_required = user_passes_test(lambda u: u.is_staff)


def index_view(request):
    return HttpResponse('Welcome to Air Seychelles new system. ' \
        '<a href="admin/">Click here to log in</a>.')

@staff_required
def apply_tag(request):
    "show a view to choose a tag and apply to selected leads..."
    id_text = request.GET.get('ids','')
    if id_text[-1] == ',':
        id_text = id_text[:-1]
    ids = map(int, id_text.split(','))

    leads = Lead.objects.filter(id__in=ids)
    tags = CRMTag.objects.all()

    if request.GET.get('submit'):

        selected_tag_ids = request.GET.getlist('tag')
        selected_tags = []

        for selected_tag_id in selected_tag_ids:
            if selected_tag_id:
                try:
                    tag = CRMTag.objects.get(id=selected_tag_id)
                except:
                    tag = CRMTag(id=selected_tag_id)
                    tag.save()
                selected_tags.append(tag)
            else:
                selected_tag_ids.remove(selected_tag_id) # Remove the empty tag that is at the end if text box is left empty

        for lead in leads:
            selected_tags.extend(lead.tags.all())
            lead.tags = selected_tags
            lead.save()

        msg_tags_changed = ','.join(selected_tag_ids)

        if len(selected_tag_ids) > 1:
            msg = "Set tags %s on %d leads" % (msg_tags_changed, leads.count())
        elif len(selected_tag_ids) == 1:
            msg = "Set tag '%s' on %d leads" % (msg_tags_changed, leads.count())
        else:
            msg = "no tags were changed"
        request.user.message_set.create(message=msg)
        return HttpResponseRedirect('/admin/crm/lead/')

    return render_to_response('admin/bulk_set_tag.html', {'leads': leads, 'tags': tags})

@staff_required
def send_emails(request):
    "Show the user a preview of their communication email and get them to confirm they want to send to the number of associated recipients"

    id = request.GET.get('id')
    ignore_previously_emailed = request.GET.get('ignore_previously_emailed')
    ignore_previously_emailed_with_same_subject = request.GET.get('ignore_previously_emailed_with_same_subject')
    communication = Communication.objects.get(id=id)

    lead_count = 0
    if request.GET.get('tag_id'):
        tag_id = request.GET.get('tag_id')
        tag = CRMTag.objects.get(id=tag_id)
        lead_count = len(Lead.objects.filter(tags=tag_id))
    
        
    if request.GET.get('confirm'):
        communication_warnings = communication.get_warnings()

        return render_to_response('admin/bulk_send_emails.html', {
            'communication': communication,
            'communication_warnings': communication_warnings,
            'id': id,
            'step': 2,
            'lead_count': lead_count,
            'tag_id': tag_id,
            'ignore_previously_emailed': ignore_previously_emailed,
            'ignore_previously_emailed_with_same_subject': ignore_previously_emailed_with_same_subject,},
            context_instance=RequestContext(request))

    elif request.GET.get('send'):
        if ignore_previously_emailed == 'on':
            ignore_previously_emailed = True
        else:
            ignore_previously_emailed = False
        
        if ignore_previously_emailed_with_same_subject == 'on':
            ignore_previously_emailed_with_same_subject = True
        else:
            ignore_previously_emailed_with_same_subject = False
        
        job = EmailJob(
                communication=communication,
                tag=tag,
                ignore_previously_emailed=ignore_previously_emailed,
                ignore_previously_emailed_with_same_subject=ignore_previously_emailed_with_same_subject
              )
        job.save()
        
        return HttpResponseRedirect('/admin/')

    else:
        tags = CRMTag.objects.all()
        return render_to_response('admin/bulk_send_emails.html', {'communication': communication, 'id': id, 'step': 1, 'tags': tags}, context_instance=RequestContext(request))


def unsubscribe(request, unsubscribe_id_base16):
    import base64
    from reportlab.lib import arciv

    try:
        key = settings.SECRET_KEY
        unsubscribe_id_arciv = base64.b16decode(unsubscribe_id_base16)
        email = arciv.decode(unsubscribe_id_arciv, key)
        lead = Lead.objects.filter(email=email)[0]

        if DontSendEntry.objects.filter(to_address=email).count() == 0:
            dont_send = DontSendEntry(to_address=email)
            dont_send.save()
        return HttpResponse("Thank you %s %s. Your email address '%s' has been unsubscribed." % (lead.first_name, lead.last_name, email))
    except (TypeError, IndexError):
        return HttpResponse("Email address not found in our system.")



@staff_required
def bulk_upload(request):
    import bulkloader
    step = 1

    from forms import LeadForm
    lf = LeadForm()
    expected_fields = lf.fields.keys()
    required_fields = ['email']   #special case as we have to fill in role and language

#    required_fields = []
#    for (name, fld) in lf.fields.items():
#        if fld.required and not fld.initial:
#            required_fields.append(name)


    if request.POST.get('pasted_content'):

        step = 2
        status = ''
        pasted_content = request.POST.get('pasted_content')

        tabular_data = bulkloader.strippedContent(pasted_content)

        #do we have some rows and some useful columns?
        early_success, dicts, early_problems = bulkloader.process(tabular_data, expected_fields, required_fields)

        late_success = True
        lead_forms = []

        data_table = [].append
        data_columns = ['email','role','language']
        if early_success:
            #may be extra columns to show
            for k in dicts[0].keys():
                if k not in data_columns:
                    data_columns.append(k)

            #check each row
            error_count = 0
            data_table('<table><tr>')
            for key in data_columns:
                data_table('<th>%s</th>' % key)
            data_table('</tr>')

            for d in dicts:

                #fill in two fields that we may not have
                if u'role' not in d:
                    d[u'role'] = settings.CRM_DEFAULT_ROLE
                if u'language' not in d:
                    d[u'language'] = 'en'


                form = LeadForm(d)
                if form.errors:
                    late_success = False
                    error_count += 1
                lead_forms.append(form)
                error_message = ''

                if form.errors:
                    data_table('<tr style="background: #f00">')
                    for e in form.errors.keys():
                        error_message += 'field %s: %s' % (e, form.errors[e])
                else:
                    data_table('<tr>')

                for i,key in enumerate(data_columns):
                    if d.has_key(key) and d[key]:
                        data_table('<td>%s</td>' % d[key])
                    else:
                        data_table('<td></td>')
                if error_message:
                    data_table('<td>%s&nbsp</td>' % error_message)
                data_table('</tr>')
            data_table('</table>')

            if late_success:
                status = 'Successfully processed %d leads, please confirm.' % len(lead_forms)
            else:
                status = '%d lead(s) out of %d had problems.' % (error_count, len(lead_forms))
        
        confirmed = request.POST.get('confirmed')
        if confirmed and late_success:
            for form in lead_forms:
                form.cleaned_data['updated_by'] = request.user
                form.cleaned_data['active'] = True
                form.save()
            msg = 'Successfully added %d leads' % len(lead_forms)
            request.user.message_set.create(message=msg)
            return HttpResponseRedirect('/admin/crm/lead/')
        return render_to_response('admin/bulk_upload.html', {
            'pasted_content': pasted_content,
            'tabular_data': tabular_data,
            'early_success': early_success,
            'early_problems': early_problems,
            'late_success': late_success,
            'status': status,
            'lead_forms': lead_forms,
            'confirmed': confirmed,
            'data_table': ''.join(data_table.__self__),
            'step': step,
            })

    roles = Role.objects.all()
    languages = Language.objects.all()
    return render_to_response('admin/bulk_upload.html', {'step': step, 'roles': roles, 'languages': languages})


@staff_required
def bulk_import(request):
    status = ''
    if request.POST.get('users'):
        from rldjango.apps.crm.models import CRMTag
        users = eval(request.POST.get('users'))
        leads_saved = 0
        for d in users:
            lead_str = 'Lead('
            for k,v in d.items():
                if k != 'tags':
                    lead_str += '%s="%s",' % (k,v)
            lead_str += 'created_by_id="%s",' % request.user.id
            lead_str += 'updated_by_id="%s",' % request.user.id
            lead_str += 'active=True'
            lead_str += ')'
            lead = eval(lead_str)
            
            try:
                lead.save()
                leads_saved += 1
            except:
                lead = Lead.objects.get(email=d['email'])
            
            if d['tags'] and isinstance(d['tags'], list):
                for tag_str in v:
                    try:
                        tag = CRMTag.objects.get(id=tag_str.strip())
                    except:
                        tag = CRMTag(id=tag_str.strip())
                        tag.save()
                    lead.tags.add(tag)
                    lead.save()
            
        msg = 'Successfully added %d leads' % leads_saved
        request.user.message_set.create(message=msg)
        return HttpResponseRedirect('/admin/crm/lead/')
    
    else:
        CRM_LEAD_IMPORT_FUNCTION = getattr(settings, 'CRM_LEAD_IMPORT_FUNCTION', '')
        users = {}
        new_users_to_import = []
        num_new_users = 0
        if CRM_LEAD_IMPORT_FUNCTION:
            path = CRM_LEAD_IMPORT_FUNCTION.split('.')
            d = {}
            exec 'import %s as m' % '.'.join(path[:-1]) in d
            users = eval('d[\'m\'].%s()' % path[-1:][0])
            tags_found = False
            if users:
                for user in users:
                    if user.has_key('email') and user['email'] and not Lead.objects.filter(email=user['email']):
                        new_users_to_import.append(user)
                    # If there are tags in the data source, we need to load all the users as tags may have been updated.
                    if not tags_found and user.has_key('tags'):
                        tags_found = True
            if new_users_to_import:
                status = 'You are about to import %d new leads from an external source. Please confirm.' % (len(new_users_to_import))
            else:
                status = 'There are no leads to import from the configured data source.'
                
            num_new_users = len(new_users_to_import)
            if not tags_found:
                users = new_users_to_import
            
        return render_to_response('admin/bulk_import.html', {'status': status, 'CRM_LEAD_IMPORT_FUNCTION': CRM_LEAD_IMPORT_FUNCTION, 'users': users, 'num_new_users': num_new_users})

@staff_required
def preview_communication(request, communication_id):
    communication = Communication.objects.get(id=communication_id)
    return render_to_response('admin/preview_communication.html', {'html': communication.message_html})


def tracking_image(request, communication_plus_check, lead_plus_check):
    """
    Returns an invisible 1px by 1px GIF image to be shown in user's HTML email if they have images enabled.
    URLs for the image are in the form http://xxx.ebrochures.org/imgid/1aaa/2bbb/
    The first part (1aaa) is the communication, second part (2bbb) is the lead.
    Both the communication and lead segments consist of the object's numeric ID followed by a 3 charater checksum.
    This helps against people who try and mess up our statistics whilst still being a pretty short URL.
    """
    
    update_email_response(communication_plus_check, lead_plus_check)
    
    # Transparent 1x1px GIF
    image = '''R0lGODlhAQABAJEAAAAAAP///////wAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw=='''
    return HttpResponse(image.decode('base64'), mimetype='image/gif')


def opt_in(request, communication_plus_check, lead_plus_check):
    update_email_response(communication_plus_check, lead_plus_check)
    return HttpResponse('Thank you for responding to our email opt-in.')


def redirect_link(request, communication_plus_check, lead_plus_check, link_plus_check):
    update_email_response(communication_plus_check, lead_plus_check, link_plus_check)
    try:
        link = LinkAddress.objects.get(id=link_plus_check[:-3])
        if link.short_check_code() == link_plus_check[-3:]:
            return HttpResponseRedirect(link.address)
    except:
        pass
    return HttpResponseNotFound('Invalid URL')

