/**
 * Given a set of coordinates for a tile, return a directory-style string.
 *
 * @param   x   Number  column
 * @param   y   Number  row
 * @param   z   Number  zoom
 *
 * @return  String  E.g. "0313131311132123" suitable for inclusion in a tile URL
 */
function coordinateToString(x, y, z)
{
    var a = [];
    
    for(var i = 0; i < z; i += 1)
    {
        var r = (y & 1);
        var c = (x & 1);
        
        a.unshift(c | (r << 1));
        
        x = x >> 1;
        y = y >> 1;
    }
    
    s = '';
    
    for(var i = 0; i < a.length; i += 1)
    {
        /*if(i > 0 && i % 2 == 0) {
            s += '/';
        }*/
    
        s += a[i].toString();
    }
    
    return s;
}

function getXYZ(layer, bounds)
{
    var res = layer.map.getResolution();
    var x = Math.round ((bounds.left - layer.maxExtent.left) / (res * layer.tileSize.w));
    var y = Math.round ((layer.maxExtent.top - bounds.top) / (res * layer.tileSize.h));
    var z = layer.map.getZoom();
    
    return [x, y, z];
}

/*
 * Returns a getURL() method for use in layer args.
 */
function getGetURLMethod(bucket_id, file_ext)
{
    return function(bounds)
    {
        var xyz = getXYZ(this, bounds);
        var x = xyz[0], y = xyz[1], z = xyz[2];
        
        return 'http://'+bucket_id+'.s3.amazonaws.com/'+z+'-r'+y+'-c'+x+'.'+file_ext;
    };
}

/**
 * Wrapper for map.
 */
function OldOaklandMap(div)
{
    /* The "correct" way to invoke a spherical mercator slippy grid map, per crshmidt's advice */
    var mapArgs = {
        maxExtent: new OpenLayers.Bounds(-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892),
        numZoomLevels: 18,
        maxResolution: 156543.0339,
        units: 'm',
        displayProjection:  new OpenLayers.Projection('EPSG:4326'),
        projection: 'EPSG:900913'
    };
    
    var layerAerialArgs = {
        buffer: 0,
        getURL: function(bounds)
        {
            var xyz = getXYZ(this, bounds);
            var x = xyz[0], y = xyz[1], z = xyz[2];
            
            // predictable? server: 0, 1, 2, 3
            var s = (x + y + z) % 4;
            
            return 'http://a'+s+'.ortho.tiles.virtualearth.net/tiles/a'+coordinateToString(x, y, z)+'.jpeg?g=90';
        }
    };

    var layerVEarthArgs = {
        buffer: 0,
        getURL: function(bounds)
        {
            var xyz = getXYZ(this, bounds);
            var x = xyz[0], y = xyz[1], z = xyz[2];
            
            // predictable? server: 0, 1, 2, 3
            var s = (x + y + z) % 4;
            
            return 'http://r'+s+'.ortho.tiles.virtualearth.net/tiles/r'+coordinateToString(x, y, z)+'.png?g=90&shading=hill';
        }
    };

    var layerOSMArgs = {
        buffer: 0,
        getURL: getGetURLMethod('osm-bayarea', 'png')
    };
    
    var layer1967Args = {
        buffer: 0,
        getURL: getGetURLMethod('oakland-1967', 'jpg')
    };

    var layer1950sArgs = {
        buffer: 0,
        getURL: getGetURLMethod('oakland-1950s', 'jpg')
    };
    
    var layer1936Args = {
        buffer: 0,
        getURL: getGetURLMethod('oakland-sf-1936', 'jpg')
    };
    
    var layer1912Args = {
        buffer: 0,
        getURL: getGetURLMethod('oakland-1912', 'jpg')
    };
    
    var layer1877Args = {
        buffer: 0,
        getURL: getGetURLMethod('oakland-1877', 'jpg')
    };
    
    this.map = new OpenLayers.Map(div, mapArgs);
    
    this.layers = {};
    this.addHistoricalLayer('Oakland 1877', layer1877Args);
    this.addHistoricalLayer('Oakland 1912', layer1912Args);
    this.addHistoricalLayer('Oakland, SF 1936', layer1936Args);
    this.addHistoricalLayer('Oakland 1950s', layer1950sArgs);
    this.addHistoricalLayer('Oakland 1967', layer1967Args);
    this.addHistoricalLayer('Present Day (OpenStreetMap)', layerOSMArgs);
    this.addHistoricalLayer('Present Day (VEarth road)', layerVEarthArgs);
    this.addHistoricalLayer('Present Day (VEarth aerial)', layerAerialArgs);

    this.map.addControl(new OpenLayers.Control.LayerSwitcher());
    
    this.setCenter(37.804656, -122.263606, 14);
}

OldOaklandMap.prototype = {

   /**
    * Project latitude and longitude before passing onto the map object.
    *
    * @param    lat     Number  latitude in degrees
    * @param    lon     Number  longitude in degrees
    * @param    zoom    Number  zoom level integer
    */
    setCenter: function(lat, lon, zoom)
    {
        var lonlat = new OpenLayers.LonLat(lon, lat);
        lonlat.transform(this.map.displayProjection, this.map.getProjectionObject());
        this.map.setCenter(lonlat, zoom);
    },
    
    addHistoricalLayer: function(name, args)
    {
        this.layers[name] = new OpenLayers.Layer.TMS(name, null, args);
        this.map.addLayer(this.layers[name]);
    },
    
    showHistoricalLayer: function(name)
    {
        this.map.setBaseLayer(this.layers[name]);
        return false;
    }
};

