 _ = require "underscore"
 Glyph = require "../glyph/glyph"
+
+class ImagePool
+
+  constructor: () ->
+    @images = []
+
+  pop: () ->
+    img = @images.pop()
+    if img?
+      return img
+    else
+      return new Image()
+
+  push: (img) ->
+    if img.constructor == Array
+      Array::push.apply(@images, img)
+    else
+      @images.push(img)
 
 class ProjectionUtils
 

    return @url.replace("{X}", x).replace('{Y}', y).replace("{Z}", z)

class WMTSTileProvider extends MercatorTileProvider

  get_tile_meter_bounds: (x, y, z) ->
    [x, y, z] = @tms_to_wmts(x, y, z)
    return super(x, y, z)

  get_image_url: (x, y, z) ->
    [x, y, z] = @tms_to_wmts(x, y, z)

    [xmax, ymax] = @meters_to_geographic(xmax, ymax)
    return [xmin, ymin, xmax, ymax]

class GridLayer

  tile_xyz_to_key: (x, y, z) ->
    return x.toString() + ":" + y.toString() + ":" + z.toString()

  key_to_tile_xyz: (key) ->
    return (parseInt(c) for c in key.split(':'))

class MercatorTileProvider extends GridLayer



  constructor: (@url, @tile_size=256) ->
    @utils = new ProjectionUtils()
    @pool = new ImagePool()
    @origin_shift = 2 * Math.PI * 6378137 / 2.0
    @initial_resolution = 2 * Math.PI * 6378137 / @tile_size
    @resolutions = (@get_resolution(z) for z in [0..30])
    @tiles = {}

  get_image_url: () ->
    throw Error "Unimplemented Method"

  get_resolution: (level) ->
    return @initial_resolution / Math.pow(2, level)

  get_level_by_extent: (extent, height, width) ->
    x_rs = (extent[2] - extent[0]) / width
    y_rs = (extent[3] - extent[1]) / height
    res = Math.max(x_rs, y_rs)

    closest = @resolutions.reduce (previous, current) ->
      return current if (Math.abs(current - res) < Math.abs(previous - res))
      return previous

    return @resolutions.indexOf(closest)

  snap_to_zoom: (extent, height, width, level) ->
    desired_res = @resolutions[level]
    desired_x_delta = width * desired_res
    desired_y_delta = height * desired_res

    [xmin, ymin, xmax, ymax] = extent
    x_adjust = (desired_x_delta - (xmax - xmin)) / 2
    y_adjust = (desired_y_delta - (ymax - ymin)) / 2

    return [xmin - x_adjust, ymin - y_adjust, xmax + x_adjust, ymax + y_adjust]

  tms_to_wmts: (x, y, z) ->
    '''Note this works both ways'''
