(function() {
  // warning CHANGES TO THIS CODE NEED TO BE ROLLED BACK INTO leaflet.py
  var expandzoom, cell_layout, layoutxyz, tiler, tiles_wrapper, zoom;

  window.tiler = tiler = {};

  cell_layout = function(items) {
    return [
      {
        y: 0,
        x: 0,
        item: items[0]
      }, {
        y: 0,
        x: 1,
        item: items[1]
      }, {
        y: 1,
        x: 0,
        item: items[2]
      }, {
        y: 1,
        x: 1,
        item: items[3]
      }
    ];
  };

  tiler.tiles_wrapper = tiles_wrapper = function(path, ext) {
    if (ext == null) { ext = "jpg"; }
    var ret = {};
    ret.get_tile_path = function(z, y, x) {
      return path + ("/z"+z+"y"+y+"x"+x+"."+ext);
    };
    return ret;
  };

  tiler.zoom = zoom = function(tiles, caption, url, x, y, z, maxzoom) {
    var c, i, k, kids, len, len1, node, r, ref, ref1;
    if (x == null) {
      x = 0;
    }
    if (y == null) {
      y = 0;
    }
    if (z == null) {
      z = 0;
    }
    if (maxzoom == null) {
      maxzoom = 3;
    }
    node = {};
    if (caption && x === 0 && y === 0) {
      node['text'] = caption;
    }
    var lastc = Math.pow(2, z) - 1;
    if (url && x === 0 && y === lastc) {
      node['url'] = url
    }
    node['image'] = tiles.get_tile_path(z, y, x);
    node['class'] = "iz"+z;
    if (z < maxzoom) {
      kids = [];
      ref = [0, 1];
      for (i = 0, len = ref.length; i < len; i++) {
        r = ref[i];
        ref1 = [0, 1];
        for (k = 0, len1 = ref1.length; k < len1; k++) {
          c = ref1[k];
          kids.push(zoom(tiles, caption, url, (x * 2) + c, (y * 2) + r, z + 1, maxzoom));
        }
      }
      node['children'] = kids;
    }
    return node;
  };

  tiler.layoutxyz = layoutxyz = function(n, x, y, z, outnode) {
    var g, i, len, ref;
    if (x == null) {
      x = 0;
    }
    if (y == null) {
      y = 0;
    }
    if (z == null) {
      z = 0;
    }
    if (outnode == null) {
      outnode = {};
    }
    outnode[x + "," + y + "," + z] = n;
    if (n.children) {
      ref = cell_layout(n.children);
      for (i = 0, len = ref.length; i < len; i++) {
        g = ref[i];
        if (g.item) {
          layoutxyz(g.item, (x * 2) + g.x, (y * 2) + g.y, z + 1, outnode);
        }
      }
    }
    return outnode;
  };

  tiler.expandzoom = expandzoom = function(node) {
    var c, ret, tilespath;
    if (node.zoomable) {
      tilespath = node.image.replace(/\/[^\/]+$/, "");
      var ext = node.image.match(/\.([^\.]+)$/);
      if (ext != null) { ext = ext[1] };
      ret = zoom(tiles_wrapper(tilespath, ext), node.text, node.url);
      return ret;
    }
    if (node.children) {
      node.children = (function() {
        var i, len, ref, results;
        ref = node.children;
        results = [];
        for (i = 0, len = ref.length; i < len; i++) {
          c = ref[i];
          if (c != null) {
              results.push(expandzoom(c));
          }
        }
        return results;
      })();
    }
    return node;
  };

  /* DynamicTiles */
  /*
  A simple GridLayer extension that takes an external "nodes" object as option,
  Nodes are keyed [x,y,z]
  and expected to be of the form: 
      {
          text: "My text",
          image" "imagepath.jpg"
      }
  */
  L.GridLayer.DynamicTiles = L.GridLayer.extend({
      createTile: function (coords, done) { // done = (err, tile)
          // console.log("createTile", coords, this.options, this.options.nodes);
          // console.log("createTile", coords);
          var tile = document.createElement('div'),
            node = this.options.nodes[coords.x+","+coords.y+","+coords.z],
            defer = false;

          tile.classList.add("tile");
          if (node != undefined) {
            // console.log("NODE", node);
            if (node.image) {
              var img = document.createElement("img");
              defer = true;
              img.addEventListener("load", function () {
                done(null, tile);
              })
              img.src = node.image;
              tile.appendChild(img);
              img.classList.add("imagetile");
            }
            if (node.text) {
                  //console.log("text", node.text);
                var textdiv = document.createElement("div");
                textdiv.innerHTML = node.text;
                tile.appendChild(textdiv);
                textdiv.classList.add("text");
                if (node.image) {
                  textdiv.classList.add("textonimage");
                }
            }
            if (node.background) {
              tile.style.color = node.background;
            }
            if (node.class) {
              tile.classList.add(node.class);
            }
            tile.classList.add("z"+coords.z);
          } else {
            tile.innerHTML = [coords.x, coords.y, coords.z].join(', ');
            tile.classList.add("coords");
          }
          // tile.style.outline = '1px solid red';
          if (!defer) {
            window.setTimeout(function () {
              done(null, tile);
            }, 250);
          }
          return tile;
      }
  });""

  L.gridLayer.dynamicTiles = function(opts) {
      return new L.GridLayer.DynamicTiles(opts);
  };

}).call(this);

(function () {


function getjson (url, callback) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = function() {
      if (request.readyState == XMLHttpRequest.DONE && request.status >= 200 && request.status < 400) {
        callback(null, JSON.parse(request.responseText));
      } else {
        callback("server error");
      }
    };
    request.onerror = function() {
        callback("connection error");
    };
    request.send();
}

var TILESIZE = 256;
var map = L.map('map', {
        editable: true,
        maxZoom: 50, // hangs past 50
        minZoom: 0,
        zoom: 0,
        crs: L.CRS.Simple,
        center: new L.LatLng(0,0),
    });

// HASH! using https://github.com/mlevans/leaflet-hash
var hash = new L.Hash(map);

getjson("index.json", function (err, data) {
    var nodes = (tiler.layoutxyz(tiler.expandzoom(data)));
    map.addLayer( L.gridLayer.dynamicTiles({
        minZoom: 0,
        tileSize: TILESIZE,
        nodes: nodes
    }) );

})

var yx = L.latLng,
    xy = function(x, y) {
        if (L.Util.isArray(x)) {    // When doing xy([x, y]);
            return yx(x[1], x[0]);
        }
        return yx(y, x);  // When doing xy(x, y);
    };

function absolutize (coords, scale, x, y) {
  // turns inkscape x,y relative path coords into absolute
  // nb flips the direction of the y axis as well 
  if (scale == null) { scale = 1.0 }
  if (x == null) { x = 0.0 }
  if (y == null) { y = 0.0 }
  var c,
    out = [];
  for (var i=0, l=coords.length; i<l; i++) {
    c = coords[i];
    x += c[0]*scale; y -= c[1]*scale;
    out.push([x, y]);
  }
  return out;
}


var xpath = [[0,0], [-7.89063,-10.6836], [7.40235,0], [4.47265,6.48438], [4.53125,-6.48438], [7.40235,0], [-7.89063,10.64453], [8.28125,11.23047], [-7.40234,0], [-4.92188,-6.91406], [-4.86328,6.91406], [-7.40234,0], [8.28125,-11.1914]];
xpath = absolutize(xpath, 10.3, 87, -128.5);
// flip it
xpath = xpath.map(function (x) { return [x[1], x[0]] });
// x = x.map(function (x) { return yx(x) });
var polyline = L.polyline(xpath, {color: '#dd2e57'}).addTo(map);

map.setView(xy(0.5 * TILESIZE, -0.5 * TILESIZE), 0);

var zoomslider = document.getElementById("zoom-slider");
zoomslider.addEventListener("input", function () {
  // console.log("zoom", zoomslider.value);
  map.flyTo([-128.0,128],zoomslider.value);
})

})();
