from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
from django.models.maps import people, tags
from django.core.template import loader
from django.core import template_loader
from django.core.extensions import DjangoContext as Context
from django.core.db import db
from django.utils.html import escape
from urlparse import urlsplit
from django.conf import settings
from django.views.decorators.vary import vary_on_cookie

import re, urllib2

def googlecode(zip=None, country=None):
  if country.lower() not in ['united states', 'united kingdom', 'canada']:
    return googlefetch("http://maps.google.com/maps?f=q&hl=en&q=%s" % (country))
  else:
    return googlefetch("http://maps.google.com/maps?f=q&hl=en&q=%s+%s" % (zip, country))

def googlefetch(url):
  geocode_url = url.replace(" ", "%20")
  geocode_request = urllib2.Request(geocode_url)
  geocode_opener = urllib2.build_opener()
  geocode_request.add_header("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1")
  try:
    geocode_data = geocode_opener.open(geocode_request).read()
  except URLError:
    return (None, None)

  #re.findall(r"""<div class=\\"ref\\"><a href=\\"/([^"]+)\\" onclick=\\"return loadUrl\(this.href\)\\">(.*?)</a></div>"""

  if "did not match any locations" in geocode_data or "We could not understand the location" in geocode_data:
    return (None, None)
  else:
    geocode_re = re.search(r"center: \{lat: ([-\d]\d+\.\d+),lng: ([-\d]\d+\.\d+)\}", geocode_data)
    if hasattr(geocode_re, 'groups'):
      return (geocode_re.group(1), geocode_re.group(2))
    else:
      return (None, None)

def index(request):
  """
    Index page.
  """
  full_tag_list = [str(tag.tag) for tag in tags.get_list()]
  full_tag_list.sort()

  t = template_loader.get_template('maps/index')
  if request.session.get('index_data', False):
    c = Context(request, {
        'google_maps_key': settings.GOOGLE_MAPS_KEY,
        'index_data': request.session.get('index_data'),
        'full_tag_list': full_tag_list,
      })
    del request.session['index_data']
  else:
    c = Context(request, {
        'google_maps_key': settings.GOOGLE_MAPS_KEY,
        'full_tag_list': full_tag_list,
      })

  return HttpResponse(t.render(c))

def profile(request):
  """
    Create a profile or update an old one (based on email).
  """

  # Turn away GETs
  if 'email' not in request.POST:
    return HttpResponseRedirect('../')

  # Check e-mail
  email_re = re.compile(r'^((([\t\x20]*[!#-\'\*\+\-/-9=\?A-Z\^-~]+[\t\x20]*|"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*")+)?[\t\x20]*<([\t\x20]*[!#-\'\*\+\-/-9=\?A-Z\^-~]+(\.[!#-\'\*\+\-/-9=\?A-Z\^-~]+)*|"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*")@(([a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9]\.)+[a-zA-Z]{2,}|\[(([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\])>[\t\x20]*|([\t\x20]*[!#-\'\*\+\-/-9=\?A-Z\^-~]+(\.[!#-\'\*\+\-/-9=\?A-Z\^-~]+)*|"[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F]*")@(([a-zA-Z0-9][-a-zA-Z0-9]*[a-zA-Z0-9]\.)+[a-zA-Z]{2,}|\[(([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\]))$')
  if not email_re.search(request.POST['email']):
    request.session['index_data'] = {
      'email': request.POST['email'],
      'infobox': "The e-mail you input doesn't seem to be valid.",
    }
    return HttpResponseRedirect('../')

  try:
    person = people.get_object(email__exact=request.POST['email'].lower())
  except people.PersonDoesNotExist:
    person = None

  t = template_loader.get_template('maps/profile')
  if person:
    tags = [obj.tag for obj in person.get_tag_list()]
    c = Context(request, {
      'person': person,
      'tags': tags,
      })
  else:
    c = Context(request, {
      'google_maps_key': settings.GOOGLE_MAPS_KEY,
      'email': request.POST['email'],
      })

  return HttpResponse(t.render(c))

def submit(request):
  """
    Proccess the posted form.
  """
  # Redirect GET
  if 'name' not in request.POST:
    return HttpResponseRedirect('../../')

  # Check that posted data (referrer) came from the same host
  if request.META['HTTP_HOST'] != urlsplit(request.META['HTTP_REFERER'])[1]:
    return HttpResponseRedirect('../../')

  # Make a nice list out of the tags
  if 'tags' in request.POST:
    tag_list = request.POST.getlist('tags')
  else:
    tag_list = None

  geocode_lat, geocode_lon = googlecode(
      zip=str(request.POST['zip']),
      country=str(request.POST['country'])
    )

  if not geocode_lat:
    request.session['index_data'] = {
      'email': request.POST['email'],
      'infobox': "Your postal code and/or country could not be geocoded, sorry.",
    }
    return HttpResponseRedirect('../')

  # Create the new or updated entry
  entry = people.Person(
      name = request.POST['name'],
      email = request.POST['email'].lower(),
      notes = request.POST['notes'],
      zip = request.POST['zip'],
      country = request.POST['country'],
      lat = geocode_lat,
      lon = geocode_lon,
    )

  # See if the email (person) exists, if so overwrite the old one, else make a new one
  try:
    entry.id = people.get_object(email__exact=request.POST['email']).id
  except people.PersonDoesNotExist:
    pass

  # Commit the person
  entry.save()

  if tag_list:
    # Create nonexistant tags
    tag_id_list = []
    bad_chars = re.compile("""[^\w\.-]""")
    for tag_item in tag_list:
      if not bad_chars.search(tag_item):
        try:
          tag_id_list.append(tags.get_object(tag__exact=tag_item.lower()).id)
        except tags.TagDoesNotExist:
          # Add Tag
          new_tag = tags.Tag(tag=tag_item)
          new_tag.save()
          tag_id_list.append(new_tag.id)
  else:
    tag_id_list = []

  # Map them to their tags
  entry.set_tags(set(tag_id_list))
  entry.save()

  # Remove unused tags
  for tag in tags.get_list():
    if not tag.get_person_list():
      tag.delete()

  # Set a session bit to show the success data in the index, redirect to index
  request.session['index_data'] = {
    'google_maps_key': settings.GOOGLE_MAPS_KEY,
    'center': "%s, %s" % (geocode_lon, geocode_lat),
    'newid': entry.id,
  }

  return HttpResponseRedirect('../../')

def ajax_tagcomplete(request, partial):
  return HttpResponse("\n".join([obj.tag for obj in tags.get_list(tag__startswith=str(partial).lower(), order_by=['tag'],)]))

def ajax_latlonrange(request, minlat, minlon, maxlat, maxlon, request_tag=None):
  if request_tag is None:
    return HttpResponse("\n".join(["\n".join((str(person.id), str(person.name), str(person.lat), str(person.lon))) for person in people.get_list(order_by=['id'], lat__gte=minlat, lon__gte=minlon, lat__lte=maxlat, lon__lte=maxlon)]))
  else:
    c = db.cursor()
    c.execute("""select p.id, p.name, p.lat, p.lon from maps_people as p
        left join maps_tags_person as pt on pt.person_id = p.id
        left join maps_tags as t on t.id = pt.tag_id
        where t.tag = '%s'
        and p.lat >= %s
        and p.lon >= %s
        and p.lat <= %s
        and p.lon <= %s
        order by p.id""" % (request_tag, minlat, minlon, maxlat, maxlon))
    r = c.fetchall()
    c.close()
    return HttpResponse("\n".join(str(item) for tup in r for item in tup))

def ajax_grabperson(request, id):
  request_person = people.get_object(pk=id)
  return HttpResponse((str(escape(request_person.notes).replace("\n","<br />"))) + "\n" + ",".join(str(item) for item in request_person.get_tag_list()))

def blank(request):
  return HttpResponse("")
