from django.contrib.gis.db import models
from osgeo import osr
import datetime
import re

REF_TYPE_CHOICES = (
    ("epsg", "EPSG"),
    ('esri', "ESRI"),
    ('iau2000', "IAU2000"),
    ("oracle9", "Oracle 9i"),
    ("oracle10", "Oracle 10g"),
    ("oracle11", "Oracle 11g"),
    ("sr-org", "spatialreference.org")
)

class SRS(models.Model):
    title = models.TextField(blank=True,null=True)
    slug = models.CharField(max_length=250,blank=True,null=True)
    description = models.TextField()
 
    wkt = models.TextField() 
    type = models.CharField(max_length=12, choices=REF_TYPE_CHOICES, default="sr-org")
    srs_id = models.IntegerField()
    
    bounds = models.PolygonField(srid=4326, null=True, blank=True)
 
    # for EPSG values, we'll override and fetch this out of the tables
    pub_date = models.DateTimeField(auto_now_add=True) 
    
    updated_date = models.DateTimeField(auto_now=True) 
 
    creator = models.CharField(max_length=255, default="Anonymous")
    views = models.IntegerField(default=0)
    objects = models.GeoManager()

    def pretty_extent(self):
        return ", ".join(map(lambda x: "%.4f" % x, self.extent()))

    def pretty_extent_native(self):
        try:
            if not self.bounds:
                return None
            bounds = self.bounds.clone()
            if self.type == 'epsg':
              bounds.transform(self.srs_id)
            else:
              # transform with WKT proj def in case of lacking epsg code
              bounds.transform(self.wkt)
            native_extent = list(bounds.extent)
            return ", ".join(map(lambda x: "%.4f" % x, native_extent))
        except:
            return None
        
    def extent(self):
        if not self.bounds:
            return None
        extent = list(self.bounds.extent)
        if extent[0] < -180:
            extent[0] = -180
        if extent[1] < -90:
            extent[1] = -90
        if extent[2] > 180:
            extent[2] = 180
        if extent[3] > 90:
            extent[3] = 90
        return extent

    def __unicode__(self):
        return "%s:%s: %s" % (self.type.upper(), self.srs_id, self.title)    
    
    def auth_name(self):
        return self.type.upper()

    def add_count(self):
        self.views += 1
        self.save()
        
    def gen_slug(self):
        if not self.title: 
            return ""
        value = re.sub('[^\w\s-]', '', self.title).strip().lower()
        value = re.sub('[-\s]+', '-', value)
        exists = SRS.objects.filter(type=self.type, slug=value).count()
        if not exists: return value
        slug = 1
        while exists:
            slug += 1
            exists = SRS.objects.filter(type=self.type, slug="%s-%s" % (value, slug)).count()
        return "%s-%s" % (value, slug)

    def save(self, force_insert=False, force_update=False):
        if not self.title:
            srs = osr.SpatialReference(self.wkt)
            title = srs.GetAttrValue("PROJCS") or srs.GetAttrValue("GEOGCS") 
            if title:
                self.title = title
        if not self.slug:
            self.slug = self.gen_slug()  
        if not self.srs_id:
            max_srs = SRS.objects.filter(type=self.type).order_by("-srs_id")
            if max_srs.count() == 0:
                self.srs_id = 1
            else:
                self.srs_id = max_srs[0].srs_id + 1
        super(SRS, self).save()

    def get_absolute_url(self):
        return "/ref/%s/%s/" % (self.type, self.srs_id)

from epsg.models import EpsgCoordinatereferencesystem
from epsg.models import EpsgCoordoperation, EpsgCoordoperationparamvalue
from epsg.models import EpsgArea, EpsgDeprecation

class EPSG(SRS):
    epsg = models.ForeignKey(EpsgCoordinatereferencesystem)
    
    def get_toWGS84(self):
	    # fetching toWGS84 stuff
        operations = EpsgCoordoperation.objects.filter( target_crs_code=4326, \
                                                        source_crs_code=self.epsg.coord_ref_sys_code
                                                      )
        methods = [a.coord_op_method for a in operations]
        y = EpsgCoordoperationparamvalue.objects.filter(coord_op_code=1797, \
                                                        coord_op_method_code__in=[9603, 9606, 9607])
    
    toWGS84 = property(get_toWGS84)

    def deprecation_info(self):
        if not self.epsg.deprecated:
            return None
        info =  EpsgDeprecation.objects.filter(object_table_name="epsg_coordinatereferencesystem", object_code=self.srs_id)
        if info.count() > 0:
            info = info[0]
        return info

    def get_bounds(self):
        from django.contrib.gis.geos import Polygon, LinearRing
        minx = self.epsg.area_of_use_code.area_west_bound_lon
        miny = self.epsg.area_of_use_code.area_south_bound_lat
        maxx = self.epsg.area_of_use_code.area_east_bound_lon
        maxy = self.epsg.area_of_use_code.area_north_bound_lat
        
        if  minx is None or \
            miny is None or \
            maxx is None or \
            maxy is None:
            return None
        
        return Polygon( \
                    LinearRing( (minx, miny), \
                                (maxx, miny), \
                                (maxx, maxy), \
                                (minx, maxy), \
                                (minx, miny)
                               )
                       )
#    bounds = property(get_bounds)
    
    
