'''
Semi-Portable recaptcha integration with django forms
Contact: Filip Sobalski <pinkeen@gmail.com>

- Add two variables to your app settings, **RECAPTCHA_PUBKEY** and **RECAPTCHA_PRIVKEY**
- Derive forms you want to have a captcha from the provided ReCaptchaForm class (how to get it working with ModelForm? any ideas?)
- * If you override the form's clean method make sure you firstly call the ReCaptchaForm's clean method *
- In your view, upon receiving the form data initialize the form object like this:
form = YouCaptchaFormClass(remoteip=request.META['REMOTE_ADDR'], data=request.POST) (or request.GET of course) - this is because reCaptcha needs the user's remote ip.
'''

from django import forms
from django.utils.safestring import mark_safe

import settings


import urllib
import urllib2


class DummyWidget(forms.Widget):
	is_hidden = True

	def render(self, name, value, attrs=None):
		return ''
		
class DummyField(forms.Field):
	
	widget = DummyWidget
	
	def clean(self, value):
		return value


class ReCaptchaWidget(forms.TextInput):
	
	def get_recaptcha_widget_html(self, field_name):
                ''' Template for this probably would be an overkill '''
		widget = u''
		widget += u'<div class="recaptcha_box" id="fdiv_%s"></div>' % field_name
		widget += u'<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>'
		widget += u'<script type="text/javascript">'
		widget += u'Recaptcha.create("%s", "fdiv_%s", {theme: "white", callback: Recaptcha.focus_response_field});' % (settings.RECAPTCHA_PUBKEY, field_name)
		widget += u'</script>'
		
		return widget
		
		
	
	def render(self, name, value, attrs=None):
		return mark_safe(self.get_recaptcha_widget_html(name))
		
class ReCaptchaResponseField(forms.Field):
	
	widget = ReCaptchaWidget
		
class ReCaptchaForm(forms.Form):
	recaptcha_response_field = ReCaptchaResponseField(label='Prove you are human')
	recaptcha_challenge_field = DummyField()
	
	def __init__(self, remoteip=None, *args, **kwargs):
		super(ReCaptchaForm, self).__init__(*args, **kwargs)
		self.remoteip = remoteip
                ''' This is a trick that makes the captcha the last field '''
		response_field = self.fields.pop('recaptcha_response_field')
		self.fields.insert(len(self.fields), 'recaptcha_response_field', response_field)
		
		
	
	def clean(self):
		cleaned_data = self.cleaned_data
		
		challenge = cleaned_data.get('recaptcha_challenge_field')
		response = cleaned_data.get('recaptcha_response_field')

		if challenge and response:
			result = self.verify_captcha(challenge, response)
			
			if not result:
				self._errors['recaptcha_response_field'] = self.error_class([u'Incorrect answer, try again.'])
				del cleaned_data['recaptcha_response_field']
			
		return cleaned_data
		
	def verify_captcha(self, challenge, response):
		url = 'http://www.google.com/recaptcha/api/verify'

		values = {
			'privatekey': settings.RECAPTCHA_PRIVKEY, 
			'remoteip' : self.remoteip, 
			'challenge' : challenge, 
			'response' : response
		}

		vrequest = urllib2.Request(url, urllib.urlencode(values))
		vresponse = urllib2.urlopen(vrequest)
		result = vresponse.read().split('\n')
		
		if result[0] == 'true':
			return True
			
		return False