# Copyright (c) 2007, Justin Bronn
# All rights reserved.
#
# Released under New BSD License
#
"""
  This module contains example models for the MaxMind(R) free
  geolocation datasets, specifically, GeoLite Country and City:
   http://www.maxmind.com/app/geolitecity
   http://www.maxmind.com/app/geoip_country

  To search for IP addresses requires long integers, however, Django
  does not yet support these fields.  These models require the BigIntegerField
  patch by Peter Nixon:
   http://code.djangoproject.com/attachment/ticket/399/django-bigint-20070712.patch
"""

from django.contrib.gis.db import models
import re

ipregex = re.compile(r'^(?P<w>\d\d?\d?)\.(?P<x>\d\d?\d?)\.(?P<y>\d\d?\d?)\.(?P<z>\d\d?\d?)$')
def ip2long(ip):
    "Converts an IP address into a long suitable for querying."
    m = ipregex.match(ip)
    if m:
        w, x, y, z = map(int, [m.group(g) for g in 'wxyz'])
        ipnum = 16777216*w + 65536*x + 256*y + z
        return ipnum
    else:
        raise TypeError, 'Invalid IP Address: %s' % ip

class IPManager(models.GeoManager):
    def ipquery(self, ip):
        "Returns any LocationBlocks matching the IP query."
        num = ip2long(ip)
        # Using select_related slows down this query a lot
        qs = self.get_query_set().filter(ipfrom__lte=num).filter(ipto__gte=num)
        if len(qs) == 1: return qs[0]
        else: return qs

class Country(models.Model, models.GeoMixin):
    name = models.CharField(maxlength=50)
    code = models.CharField(maxlength=2)
    point = models.PointField(null=True)
    objects = models.GeoManager()
    def __unicode__(self): return self.name

class CountryBlock(models.Model):
    ipfrom = models.BigIntegerField(db_index=True)
    ipto = models.BigIntegerField(db_index=True)
    startip = models.IPAddressField()
    endip = models.IPAddressField()
    country = models.ForeignKey(Country)
    objects = IPManager()
    def __unicode__(self): return unicode('%s: %s to %s' % (self.country.name, self.startip, self.endip))

class Location(models.Model, models.GeoMixin):
    locid = models.IntegerField(db_index=True)
    country = models.ForeignKey(Country)
    region = models.CharField(maxlength=7, blank=True)
    city = models.CharField(maxlength=41, blank=True)
    postalcode = models.CharField(maxlength=7, blank=True)
    dmacode = models.CharField(maxlength=3, blank=True)
    areacode = models.CharField(maxlength=3, blank=True)
    point = models.PointField()
    objects = models.GeoManager()
    def __unicode__(self):
        return unicode('Location %d: %s - %s, %s %s' % (self.locid, self.country.name, self.region, self.city, self.postalcode))

class LocationBlock(models.Model):
    location = models.ForeignKey(Location)
    ipfrom = models.BigIntegerField(db_index=True)
    ipto = models.BigIntegerField(db_index=True)
    objects = IPManager()