""" Mapnik UTFGrid Provider.
Only works with mapnik2 (Where the Grid functionality was introduced)

Sample configuration:

    "provider":
    {
      "class": "TileStache.Goodies.Providers.MapnikGrid:Provider",
      "kwargs": { "mapfile": "mymap.xml", "fields":["name","address"] }
    }

mapfile: the mapnik xml file to load the map from
fields: The fields that should be added to the resulting grid json.

"""
import json
import mapnik2 as mapnik
from TileStache.Geography import getProjectionByName

class Provider:

    def __init__(self, layer, mapfile, fields):
        """
        """
        self.mapnik = None
        self.layer = layer
        self.mapfile = mapfile
        #De-Unicode the strings or mapnik gets upset
        self.fields = list(str(x) for x in fields)

        self.mercator = getProjectionByName('spherical mercator')

    def renderTile(self, width, height, srs, coord):
        """
        """
        if self.mapnik is None:
            self.mapnik = mapnik.Map(0, 0)
            mapnik.load_map(self.mapnik, str(self.mapfile))

        nw = self.layer.projection.coordinateLocation(coord)
        se = self.layer.projection.coordinateLocation(coord.right().down())
        ul = self.mercator.locationProj(nw)
        lr = self.mercator.locationProj(se)


        self.mapnik.width = width
        self.mapnik.height = height
        self.mapnik.zoom_to_box(mapnik.Box2d(ul.x, ul.y, lr.x, lr.y))

        # create grid as same size as map/image
        grid = mapnik.Grid(width, height)
        # render a layer to that grid array
        mapnik.render_layer(self.mapnik,grid,layer=0,fields=self.fields)
        # then encode the grid array as utf, resample to 1/4 the size, and dump features
        grid_utf = grid.encode('utf',resolution=4,add_features=True)

        return SaveableResponse('grid(' + json.dumps(grid_utf) + ')')

    def getTypeByExtension(self, extension):
        """ Get mime-type and format by file extension.

            This only accepts "json".
        """
        if extension.lower() != 'json':
            raise KnownUnknown('MapnikGrid only makes .json tiles, not "%s"' % extension)

        return 'text/json', 'JSON'

class SaveableResponse:
    """ Wrapper class for JSON response that makes it behave like a PIL.Image object.

        TileStache.getTile() expects to be able to save one of these to a buffer.
    """
    def __init__(self, content):
        self.content = content

    def save(self, out, format):
        if format != 'JSON':
            raise KnownUnknown('MapnikGrid only saves .json tiles, not "%s"' % format)

        out.write(self.content)

@@ -22,16 +22,242 @@
 ovider.%0A
+Takes the first layer from the given mapnik xml file and renders it as UTFGrid%0Ahttps://github.com/mapbox/mbtiles-spec/blob/master/1.1/utfgrid.md%0AIt can then be used for this:%0Ahttp://mapbox.github.com/wax/interaction-leaf.html%0A
 Only wor
@@ -319,16 +319,75 @@
 duced)%0A%0A
+Use Sperical Mercator projection and the extension %22json%22%0A%0A
 Sample c
@@ -505,18 +505,32 @@
 kwargs%22:
+%0A      %7B%0A      
  
-%7B
  %22mapfil
@@ -546,16 +546,25 @@
 p.xml%22, 
+%0A        
 %22fields%22
@@ -582,16 +582,95 @@
 ddress%22%5D
+,%0A        %22layer_index%22: 0,%0A        %22wrapper%22: %22grid%22,%0A        %22scale%22: 4%0A     
  %7D%0A    %7D
@@ -789,16 +789,318 @@
 d json.%0A
+layer_index: The index of the layer you want from your map xml to be rendered%0Awrapper: If not included the json will be output raw, if included the json will be wrapped in %22wrapper(JSON)%22 (for use with wax)%0Ascale: What to divide the tile pixel size by to get the resulting grid size. Usually this is 4.
 %0A%22%22%22%0Aimp
@@ -1249,16 +1249,54 @@
 , fields
+, layer_index=0, wrapper=None, scale=4
 ):%0A     
@@ -1399,16 +1399,113 @@
 mapfile%0A
+        self.layer_index = layer_index%0A        self.wrapper = wrapper%0A        self.scale = scale%0A
         
@@ -2434,17 +2434,32 @@
 d,layer=
-0
+self.layer_index
 ,fields=
@@ -2530,17 +2530,21 @@
 le to 1/
-4
+scale
  the siz
@@ -2612,17 +2612,26 @@
 olution=
-4
+self.scale
 ,add_fea
@@ -2655,37 +2655,165 @@
     
-return SaveableResponse('grid
+if self.wrapper is None:%0A                return SaveableResponse(json.dumps(grid_utf))%0A        else:%0A                return SaveableResponse(self.wrapper + '
 (' +

Add more parameters and improve the documentation.