#!/usr/bin/python
from math import pi,cos,sin,log,exp,atan
from subprocess import call
import sys, os, cgi, mapnik
import resource

DEG_TO_RAD = pi/180
RAD_TO_DEG = 180/pi

#Used some stuff from the generate_tiles.py script
def minmax (a,b,c):
  a = max(a,b)
  a = min(a,c)
  return a

class GoogleProjection:
  def __init__(self,levels=18):
    self.Bc = []
    self.Cc = []
    self.zc = []
    self.Ac = []
    c = 256
    for d in range(0,levels):
      e = c/2;
      self.Bc.append(c/360.0)
      self.Cc.append(c/(2 * pi))
      self.zc.append((e,e))
      self.Ac.append(c)
      c *= 2

  def fromLLtoPixel(self,ll,zoom):
     d = self.zc[zoom]
     e = round(d[0] + ll[0] * self.Bc[zoom])
     f = minmax(sin(DEG_TO_RAD * ll[1]),-0.9999,0.9999)
     g = round(d[1] + 0.5*log((1+f)/(1-f))*-self.Cc[zoom])
     return (e,g)

  def fromPixelToLL(self,px,zoom):
     e = self.zc[zoom]
     f = (px[0] - e[0])/self.Bc[zoom]
     g = (px[1] - e[1])/-self.Cc[zoom]
     h = RAD_TO_DEG * ( 2 * atan(exp(g)) - 0.5 * pi)
     return (f,h)

def render_tile(x, y, mapfile, tile_dir, z):
	#fix dir
  if not os.path.isdir(tile_dir):
     os.mkdir(tile_dir)

	#General tile setup stuff
  gprj = GoogleProjection(z+1)
  m = mapnik.Map(2 * 256,2 * 256)
  prj = mapnik.Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over")
  mapnik.load_map(m,mapfile)

  zoom = str(z);
  if not os.path.isdir(tile_dir + zoom):
    os.mkdir(tile_dir + zoom)

  p0 = gprj.fromPixelToLL((x * 256.0, (y+1) * 256.0),z)
  p1 = gprj.fromPixelToLL(((x+1) * 256.0, y * 256.0),z)

  str_x = str(x)
  str_y = str(y)
  if not os.path.isdir(tile_dir + zoom + '/' + str_x):
    os.mkdir(tile_dir + zoom + '/' + str_x)

  # render a new tile and store it on filesystem
  c0 = prj.forward(mapnik.Coord(p0[0],p0[1]))
  c1 = prj.forward(mapnik.Coord(p1[0],p1[1]))

  bbox = mapnik.Envelope(c0.x,c0.y,c1.x,c1.y)
  bbox.width(bbox.width() * 2)
  bbox.height(bbox.height() * 2)
  m.zoom_to_box(bbox)

  tile_uri = tile_dir + zoom + '/' + str_x + '/' + str_y + '.png'
  
  im = mapnik.Image(512, 512)
  mapnik.render(m, im)
  view = im.view(128,128,256,256) # x,y,width,height
  view.save(tile_uri ,'png')

	#reduce that baby
  #os.system('/opt/cherokee/bin/convert -colors 255 -alpha on ' + tile_uri + ' ' + tile_uri)

def main():
	#We assume it should be rendered within 60 seconds
	#resource.setrlimit(resource.RLIMIT_CPU,(60,70))

	#Get the URL
	qstr = os.environ["REDIRECT_URL"]
	qstr = qstr.split("/")

	#Basic stuff
	#mapfile = "/home/mapnik/mapnik/osm-local.xml"
	mapfile = "/home/rullzer/stylesheets/osm.xml"
	tiledir = "/home/rullzer/tiles/"
	if (len(qstr) == 5):
		layer = qstr[1]
		zoom = int(qstr[2])
		x = int(qstr[3])
		y = int(qstr[4].split(".")[0])
		if (layer == "basemap"):
			mapfile = "/home/rullzer/stylesheets/osm-base-map.xml"
			tiledir = "/home/rullzer/tiles/basemap/"
		elif (layer == "fietsroutes"):
			mapfile = "/home/rullzer/stylesheets/osm-fietsroutes-overlay.xml"
			tiledir = "/home/rullzer/tiles/fietsroutes/"
		elif (layer == "roads"):
			mapfile = "/home/rullzer/stylesheets/osm-roads.xml"
			tiledir = "/home/rullzer/tiles/roads/"
		elif (layer == "fietsroutes-ncn"):
			mapfile = "/home/rullzer/stylesheets/osm-fietsroutes-ncn-overlay.xml"
			tiledir = "/home/rullzer/tiles/fietsroutes-ncn/"
		elif (layer == "fietsroutes-rcn"):
			mapfile = "/home/rullzer/stylesheets/osm-fietsroutes-rcn-overlay.xml"
			tiledir = "/home/rullzer/tiles/fietsroutes-rcn/"
		elif (layer == "fietsroutes-lcn"):
			mapfile = "/home/rullzer/stylesheets/osm-fietsroutes-lcn-overlay.xml"
			tiledir = "/home/rullzer/tiles/fietsroutes-lcn/"
		elif (layer == "ov"):
			mapfile = "/home/rullzer/stylesheets/osm-ov-overlay.xml"
			tiledir = "/home/rullzer/tiles/ov/"
		elif (layer == "wandelroutes"):
			mapfile = "/home/rullzer/stylesheets/osm-wandelroutes-overlay.xml"
			tiledir = "/home/rullzer/tiles/wandelroutes/"
		elif (layer == "pois"):
			mapfile = "/home/rullzer/stylesheets/osm-pois.xml"
			tiledir = "/home/rullzer/tiles/pois/"
		elif (layer == "places"):
			mapfile = "/home/rullzer/stylesheets/osm-places.xml"
			tiledir = "/home/rullzer/tiles/places/"
		elif (layer == "carnaval"):
			mapfile = "/home/rullzer/stylesheets/osm-local-carnaval.xml"
			tiledir = "/home/rullzer/tiles/carnaval/"
		elif (layer == "frysk"):
			mapfile = "/home/rullzer/stylesheets/osm-local-fy.xml"
			tiledir = "/home/rullzer/tiles/frysk/"
		elif (layer == "detour"):
			mapfile = "/home/rullzer/stylesheets/osm-detour-routes.xml"
			tiledir = "/home/rullzer/tiles/detour/"
		elif (layer == "coffeeshop"):
			mapfile = "/home/rullzer/stylesheets/osm-coffeeshops.xml"
			tiledir = "/home/rullzer/tiles/coffeeshop/"
		elif (layer == "recreational"):
			mapfile = "/home/rullzer/stylesheets/osm-recreational-routes.xml"
			tiledir = "/home/rullzer/tiles/recreational/"
	else:
		#Split URL
		zoom = int(qstr[1])
		x = int(qstr[2])
		y = int(qstr[3].split(".")[0])

	#render tile
	#print "Content-type: plain/txt\n"
	#print zoom, x, y
	#return
	render_tile(x, y, mapfile, tiledir, zoom)

	filename = "/home/rullzer/tiles" + os.environ["REDIRECT_URL"]

	if os.path.exists(filename) and os.path.isfile(filename):
		print "Content-type: image/png\n"
		print file(filename, 'rb').read()
	else:
		print 'Status: 500'

	#Return the tile
	#print "Content-type: image/png\n"
	# AFBLIJVEN!
	#print file("/home/rullzer/tiles" + os.environ["REDIRECT_URL"], "rb").read()

	#print "Location: " + os.environ["QUERY_STRING"] + "\n\n" a

	#print "Location:" + os.environ["QUERY_STRING"]
#print "Status: 404"
#print "Content-type: text/plain\n"
#print os.environ

main()
