var geocoder, mapviewer, geocode_markers = [];

var options, icons = {};
var iphone = false;

function showIPhoneMapTypes() {
    $('widgetholder').className += ' active';
}

function hideIPhoneMapTypes() {
    $('widgetholder').className = $('widgetholder').className.replace( new RegExp( ' ?active' ), '' );
}

var gesture_pos, gesture_moving = false;
var skip_gesture = false;

function handleGesture( e ) {
    if( skip_gesture ) {
        skip_gesture = false;
        return;
    }
    /*
    console.log( e.type );
    pos = new MMPoint( e.layerX, e.layerY );
    e.bubbles = false;
    e.cancelBubble = true;
    if( e.type == 'gesturestart' ) {
        console.log( 'pos='+pos.toString() );
        gesture_pos = pos;
        gesture_moving = false;
    } else if( e.type == 'gesturechange' ) {
        var step = new MMPoint( pos.x - gesture_pos.x, pos.y - gesture_pos.y );
        if( ! gesture_moving ) {
            console.log( 'step='+step.toString() );
            if( step.x > 10 || step.y > 10 ) {
                gesture_moving = true;
            }
        }
        if( gesture_moving ) {
            console.log( 'moving='+step.toString() );
            mapviewer.setOption( 'smoothpan', false );
            mapviewer.moveMap( step );
            mapviewer.setOption( 'smoothpan', true );
            gesture_pos = pos;
        }
    }

    */
    if( e.type == 'gestureend' && e.scale != 1 && e.scale != 0 ) {
        // This ended up doing my head in so I've just hardcoded
        // it to be either +/- 1 or 2
        var zf = mapviewer.getZoomFactor();
        if( e.scale > 1 ) {
            if( e.scale > 2 ) {
                zf += 2;
            } else {
                zf += 1;
            }
        } else {
            if( e.scale < 0.5 ) {
                zf -= 2;
            } else {
                zf -= 1;
            }
        }
        mapviewer.setZoomFactor(zf);
        skip_gesture = true;
    }
}

var touchID;
var lastTouch;

function handleTouch(e) {
    if( e.touches.length == 1 ) {
        var t = e.touches[0];
        pos = new MMPoint( t.clientX, t.clientY );
        if( t.identifier == touchID ) {
            var step = new MMPoint( lastTouch.x - pos.x, lastTouch.y - pos.y );
            mapviewer.moveMap( step );
            lastTouch = pos;
        } else {
            lastTouch = pos;
            touchID = t.identifier;
        }
    }
    cancelDefaults(e);
}

function cancelDefaults(e) {
    e.preventDefault();
}

function recenterMap( type, target, pos ) {
    if( target == mapviewer ) {
        mapviewer.goToPosition( pos );
    }
}

function onLoad() {
	mapviewer = MMFactory.createViewer( $( 'map' ) );
    if( ( String( navigator.userAgent ) ).indexOf( 'iPhone' ) != -1 ||
        ( String( navigator.userAgent ) ).indexOf( 'iPad' ) != -1 ) {
        iphone = true;
        document.body.className += ' iPhone'
        mapviewer.setOption( 'smoothpan', false );
        //$('map').addEventListener( 'touchmove', handleTouch );
        mapviewer.addEventHandler( 'click', recenterMap  );
        //$('map').addEventListener( 'touchmove', cancelDefaults );
        //$('map').addEventListener( 'touchstart', cancelDefaults );
        $('map').addEventListener( 'gesturestart', handleGesture );
        $('map').addEventListener( 'gesturechange', handleGesture );
        $('map').addEventListener( 'gestureend', handleGesture );
    }
    mapviewer.removeMapType( MM_WORLD_BIRDSEYE );
    mapviewer.removeMapType( MM_WORLD_BEHYBRID );
    addOSM( mapviewer );
    mapviewer.addMapType( MM_WORLD_BIRDSEYE );
    mapviewer.addMapType( MM_WORLD_BEHYBRID );
    var mtw;
    if( iphone ) {
        mapviewer.addWidget( new MMMessageWidget( '<a href="javascript:void(0)" id="maptypelink">Map types</a>', { 'closebutton' : false } , new MMBox( 21, null, null, 2 ) ) );
        $('maptypelink').onclick = showIPhoneMapTypes;
        $('closewidgetholder').onclick = hideIPhoneMapTypes;
        mtw = new MMMapTypeWidget( null, new MMBox( 25, null, null, 90 ) );
        mtw.setContainer( $('widgetholder') );
    } else {
        mtw = new MMMapTypeWidget();
        mapviewer.addWidget( new MMPanZoomWidget() );
        mapviewer.addWidget( new MMLocationWidget() );
        mapviewer.addWidget( new MMMessageWidget( '<a href="javascript:void(0)" id="editlink">Edit this area</a>', { 'closebutton' : false } , new MMBox( 10, 11 ) ) );
    }
    mtw.setMenuProperties( custom_map_types['mapnik'].map, {
        'heading_text': 'Options',
        'label': 'Normal'
        } );
    mtw.addRelationship( custom_map_types['mapnik'].map, custom_map_types['noname'].map, {
        'label' : 'Unnamed roads'
        } );
    mtw.addRelationship( custom_map_types['mapnik'].map, custom_map_types['mobile'].map, {
        'label' : 'Mobile'
        } );
    mtw.setMenuProperties( custom_map_types['osmarender'].map, {
        'heading_text': 'Mapping Errors',
        'label': 'Hidden'
        } );
    mtw.addRelationship( custom_map_types['osmarender'].map, maplint.map, {
        'label': 'Visible'
        } );
    mapviewer.addWidget( mtw );
    mapviewer.setOption( 'mousewheel:wheeldown', 'zoomout' );
    mapviewer.setOption( 'mousewheel:wheelup', 'zoomin' );
    mapviewer.addEventHandler( 'mousemove', handleMouseOver );
    mapviewer.addEventHandler( 'mapBoundsChanged', updateHash );
    mapviewer.addEventHandler( 'changeMapType', updateHash );
    mapviewer.addEventHandler( 'changeMapType', hideIPhoneMapTypes );
    //mapviewer.addEventHandler( 'endGeocode', endGeocode );
    mapviewer.addEventHandler( 'locationUpdate', locationUpdate );
    mapviewer.addEventHandler( 'contextMenu', handleContextMenu );
    options = parseHash(mapviewer);
    if( options.scene ) {
        mapviewer.setBirdsEyeSceneById( options.scene, options.location.coords );
        mapviewer.setZoomFactor(options.location.zoom_factor);
    } else {
        mapviewer.setMapType( options.map_type );
        mapviewer.goToPosition( options.location );
    }
    if( options.marker ) {
        mapviewer.createMarker( options.marker, { 'label' : options.title } );
    }
    
    $('clicked').onkeyup = placeMarker;
    geocoder = new MMGeocoder( endGeocode );
    var form = $('queryform');
    if( form )
        form.onsubmit = handleQuery;

    icons['twitter'] = MM_DEFAULT_ICON.copy();
    icons['twitter'].image = '/map/twitter-marker.png';
    icons['twitter'].groupName = 'twitter';
    icons['twittercluster'] = MM_DEFAULT_CLUSTER_ICON.copy();
    icons['twittercluster'].image = '/map/twitter-marker-multiple.png';
    icons['flickr'] = MM_DEFAULT_ICON.copy();
    icons['flickr'].image = '/map/flickr-marker.png';
    icons['flickr'].groupName = 'flickr';
    icons['flickrcluster'] = MM_DEFAULT_CLUSTER_ICON.copy();
    icons['flickrcluster'].image = '/map/flickr-marker-multiple.png';
    icons['current'] = new MMIcon( 'http://www.multimap.com/mmw/i/markers/tube_marker.png' );
    icons['current'].iconAnchor = new MMPoint( 13, 13 );
    icons['current'].iconSize = new MMDimensions( 25, 25 );
    icons['current'].zIndex = -2;
    icons['point'] = new MMIcon( '/map/gpspoint-11.png' );
    icons['point'].iconSize = new MMDimensions( 11, 11 );
    icons['point'].iconAnchor = new MMPoint( 6, 6 );
    icons['point'].infoBoxAnchor = new MMPoint( 5, 6 );
    icons['point'].className = 'MMMarker';
    icons['point'].zIndex = -1;

    mapviewer.declutterGroup( 'twitter', { 'cluster_icon' : icons['twittercluster'], 'hide_index' : true } );
    mapviewer.declutterGroup( 'flickr', { 'cluster_icon' : icons['flickrcluster'], 'hide_index' : true } );

    $('showall').onclick = showJohn;
    $('autoscale').onclick = toggleAutoScale;
    if( window.location.search.indexOf( 'show=john' ) > -1 ) {
        //requestJohn();
        //requestTwitter();
        requestPhotos();
    }
}

var autoscaling = true;

function toggleAutoScale() {
    autoscaling = ! autoscaling;
    var as = $('autoscale');
    while( as.firstChild ) {
        as.removeChild( as.firstChild );
    }
    as.appendChild( document.createTextNode( autoscaling ? 'Disabled' : 'Enable' ) );
}

function showJohn() {
    if( john_locs && john_locs.length > 0 ) {
        var locs = [];
        for( var i = 0, l = john_locs.length; i < l; ++i ) {
            locs.push( new MMLatLon( john_locs[i].lat, john_locs[i].lon ) );
        }
        mapviewer.goToPosition( mapviewer.getAutoScaleLocation( locs ) );
    }
}

var photos, photo_overlays = [];

function requestPhotos() {
    var url = 'http://johnmckerrell.com/map/flickr.xml?rand='+Math.random();
    var x = mapviewer.getXMLHTTPRequest();
    x.open( 'GET', url, true );
    x.onreadystatechange = function() {
        if( x.readyState == 4 ) {
            var photos_xml = mapviewer.parseXML( x.responseText );
            var items = photos_xml.getElementsByTagName( 'item' );
            photos = [];
            var photo, photo_xml;
            for( var i = 0, l = items.length; i < l; ++i ) {
                photo = {};
                photo_xml = items[i].getElementsByTagName( '*' );
                for( var j = 0, jl = photo_xml.length; j < jl; ++j ) {
                    if( photo_xml[j] && photo_xml[j].firstChild
                     && photo_xml[j].firstChild.nodeValue
                     && photo_xml[j].firstChild.nodeValue != '' 
                        ) {
                        photo[photo_xml[j].nodeName] = photo_xml[j].firstChild.nodeValue;
                    }
                }
                photos.push( photo );
            }
            updatePhotos( );
            setTimeout( requestTwitter, 300000 );
        }
    };
    x.send(null);
}

function updatePhotos() {
    if( ! ( photos ) )
        return;
    
    while( photo_overlays.length ) {
        mapviewer.removeOverlay( photo_overlays.shift() );
    }
    var loc = 0;
    //var loclen = john_locs.length;
    var photo = photos.length - 1;
    var ldate, tdate, marker;
    /*
    tdate = new Date();
    ldate = new Date();
    ldate.setTime( Date.parse( john_locs[loc].time_logged ) );
    while( photo >= 0 && loc < loclen ) {
        if( photos[photo]['geo:lat'] ) {
            continue;
        }
        tdate.setTime( Date.parse( photos[photo]['dc:date.Taken'] ) );
        while( loc < loclen && tdate > ldate ) {
            ++loc;
            if( loc < loclen ) {
                ldate.setTime( Date.parse( john_locs[loc].time_logged ) );
            }
        }
        if( loc < loclen ) {
            marker = mapviewer.createMarker( new MMLatLon( john_locs[loc].lat, john_locs[loc].lon ), { 'icon' : icons['twitter'] } );
            marker.setInfoBoxContent( '<div class="twittertext"><p>'+twitters[tweet].text+'...</p><p class="twitterdate"><a target="_blank" href="http://twitter.com/mcknut/statuses/'+twitters[tweet].id+'">'+tdate+'</p></div>' );
            twitter_overlays.push( marker );
        }
        --tweet;
    }
    */
    for( var i = 0, l = photos.length; i < l; ++i ) {
        if( photos[i]['geo:lat'] ) {
            marker = mapviewer.createMarker( new MMLatLon( photos[i]['geo:lat'], photos[i]['geo:long'] ), { 'icon' : icons['flickr'] } );
            marker.setInfoBoxContent( '<div class="photo">'+photos[i]['description']+'</div>' );
            twitter_overlays.push( marker );
        }
    }
}


var twitters, twitter_overlays = [];

function requestTwitter() {
    var url = 'http://johnmckerrell.com/map/twitter.json?rand='+Math.random();
    var x = mapviewer.getXMLHTTPRequest();
    x.open( 'GET', url, true );
    x.onreadystatechange = function() {
        if( x.readyState == 4 ) {
            var json, jsonstr = 'json='+x.responseText;
            eval( jsonstr );
            twitters = json;
            updateTwitter();
            setTimeout( requestTwitter, 300000 );
        }
    };
    x.send(null);
}

function updateTwitter() {
    if( ! ( john_locs && twitters ) )
        return;
    
    while( twitter_overlays.length ) {
        mapviewer.removeOverlay( twitter_overlays.shift() );
    }
    var loc = 0;
    var loclen = john_locs.length;
    var tweet = twitters.length - 1;
    var ldate, tdate, marker;
    tdate = new Date();
    ldate = new Date();
    ldate.setTime( Date.parse( john_locs[loc].time_logged ) );
    while( tweet >= 0 && loc < loclen ) {
        tdate.setTime( Date.parse( twitters[tweet].created_at ) );
        while( loc < loclen && tdate > ldate ) {
            ++loc;
            if( loc < loclen ) {
                ldate.setTime( Date.parse( john_locs[loc].time_logged ) );
            }
        }
        if( loc < loclen ) {
            makeTwitterOverlay( john_locs[loc], twitters[tweet], tdate );
        } else if( loc == loclen ) {
            makeTwitterOverlay( john_locs[loclen-1], twitters[tweet], tdate );
        }
        --tweet;
    }
}

function makeTwitterOverlay( loc, tweet, tdate ) {
    marker = mapviewer.createMarker( new MMLatLon( loc.lat, loc.lon ), { 'icon' : icons['twitter'] } );
    marker.setInfoBoxContent( '<div class="twittertext"><p>'+tweet.text+'...</p><p class="twitterdate"><a target="_blank" href="http://twitter.com/mcknut/statuses/'+tweet.id+'">'+tdate+'</p></div>' );
    twitter_overlays.push( marker );
}

var last_script_tag 
function requestJohn() {
    var url = 'http://johnmckerrell.com/map/john.json?rand='+Math.random();
    var s = document.createElement( 'script' );
    s.setAttribute( 'type', 'text/javascript' );
    s.setAttribute( 'src', url );
    document.getElementsByTagName( 'head' )[0].appendChild( s );
    last_script_tag = s;
}

var john_locs, john_overlays = [];

function updateJohn( results ) {
    while( john_overlays.length ) {
        mapviewer.removeOverlay( john_overlays.shift() );
    }
    clearSVGPaths();
    var ls = results.locations;
    var marker, description, loc, ll, locs = [];
    var recent = [];
    for( var i = 0, l = ls.length; i < l; ++i ) {
        loc = ls[i];
        ll = new MMLatLon( loc.lat, loc.lon );
        locs.push( ll );
        recent.push( ll );
        if( recent.length > 20 )
            recent.shift();
        description = loc.local_area +', '+loc.state+', '+loc.country_code;
        marker = mapviewer.createMarker( ll,
            {
                'icon' : icons['point'],
                'label' : description
            } );
        marker.setInfoBoxContent( '<h3>'+description+'</h3><p>'+loc.time_logged+'</p>' );
        john_overlays.push( marker );
    }
    john_overlays.push( mapviewer.createMarker( new MMLatLon( loc.lat, loc.lon ),
        {
            'icon' : icons['current'],
            'inert' : true
        } ) );
    var line = new MMPolyLineOverlay( locs, { 'opacity' : 0.5 } );
    mapviewer.addOverlay( line );
    john_overlays.push( line );
    if( autoscaling ) {
        mapviewer.goToPosition( mapviewer.getAutoScaleLocation( recent ) );
    }
    addSVGPaths();
    var last_time = new Date();
    last_time.setTime( Date.parse( loc.time_logged ) );
    $('status').innerHTML = "Last checked: "+(new Date())+"<br/>Last updated: "+last_time;
    $('coords').style.display = 'block';
    john_locs = ls;
    updateTwitter();
    updatePhotos();
    setTimeout( requestJohn, 300000 );
}

var svgs;

function addSVGPaths() {
    var svgs_collection = document.getElementsByTagName( 'path' );
    if( ! svgs_collection )
        return;
    svgs = [];
    for( var i = 0, l = svgs_collection.length; i < l; ++i ) {
        svgs.push( { 'path' : svgs_collection[i] } );
    }
    for( var i = 0, l = svgs.length; i < l; ++i ) {
        var parts = [];
        for( var j = 1; j < 5; ++j ) {
            var path = document.createElementNS('http://www.w3.org/2000/svg', 'path' );
            path.setAttribute( 'd', svgs[0].path.getAttribute( 'd' ) );
            path.setAttribute( 'class', 'arrow-core arrow-core-'+j );
            path.setAttribute( 'fill', 'none' );
            path.setAttribute( 'opacity', '0.75' );
            path.setAttribute( 'stroke-linejoin', 'round' );
            svgs[0].path.parentNode.appendChild( path );
            parts.push( path );
        }
        svgs[i]['parts'] = parts;
    }
    mapviewer.addEventHandler( 'endPan', updateArrowSVGS );
    mapviewer.addEventHandler( 'changeZoom', updateArrowSVGS );
}

function updateArrowSVGS( type, target ) {
    if( ! svgs )
        return;

    for( var i = 0, l = svgs.length; i < l; ++i ) {
        for( var j = 0, lj = svgs[i].parts.length; j < lj; ++j ) {
            svgs[i].parts[j].setAttribute( 'd', svgs[i].path.getAttribute( 'd' ) );
        }
    }
}

function clearSVGPaths() {
    if( ! svgs )
        return;

    for( var i = 0, l = svgs.length; i < l; ++i ) {
        for( var j = 0, lj = svgs[i].parts.length; j < lj; ++j ) {
            svgs[i].parts[j].parentNode.removeChild( svgs[i].parts[j] );
        }
    }
    delete svgs;
}


var user_marker;

function placeMarker( e ) {
    if( ! e )
        e = window.event;
    if( e.keyCode == 13 ) {
        var pos = $('clicked').value;
        pos = pos.replace( /[^0-9-,.]/g, '' );
        pos = pos.split( ',' );
        pos = new MMLatLon( pos[0], pos[1] );
        if( user_marker )
            mapviewer.removeOverlay( user_marker );
        user_marker = mapviewer.createMarker( pos );
    }
}

function handleMouseOver( type, target, step ) {
    if( target instanceof MultimapViewer ) {
        var dims = mapviewer.getDimensions();
        step.x += dims.width / 2;
        step.y += dims.height / 2;
        var pos = mapviewer.getMapPositionAt( step );
        $('over').value = '('+pos.lat+','+pos.lon+')';
    }
}

function handleClick( type, target, pos ) {
    if( target instanceof MMMarkerOverlay && target.getAttribute( 'geocode_result' ) ) {
        var zoom_factor = target.getAttribute( 'zoom_factor' );
        if( mapviewer.getZoomFactor() > zoom_factor )
            zoom_factor = null;
        mapviewer.goToPosition( target.getPosition(), zoom_factor );
    }
    if( target instanceof MultimapViewer ) {
        $('clicked').style.display = 'block';
        $('clicked').value = '('+pos.lat+','+pos.lon+')';
    }
}

function handleContextMenu( type, target, menu, pos, step ) {
    var func = function() {
        //http://dev.openstreetmap.org/~ojw/NeedRender/?x=2002&y=1596&priority=1&src=InformationFreeway:mcknut&random=1193423153733
        var proj = new MMMercatorProjection(15);
        var pixel = proj.fromLatLonToPixel( pos, 13 );
        var tile = mapviewer.map.coordToTile( pixel.x, pixel.y, 13, 256, 256 );
        tile.x = Math.floor( tile.x );
        tile.y = Math.floor( tile.y );
        var url = 'http://tah.openstreetmap.org/Request/create/?x='+tile.x+'&y='+tile.y+'&random='+Math.random();
        //var url = 'http://tah.openstreetmap.org/NeedRender/?x='+tile.x+'&y='+tile.y+'&priority=1&src=johnmckerrell.com:mcknut&z=12&random='+Math.random();
        window.open( url );
        menu.remove();
    };
    menu.addItem( new MMMenuItem( 'Request re-render', func, null, 10 ) );
    if( mapviewer.getMapType() instanceof MMMapType ) {
        var func = function() {
            //http://dev.openstreetmap.org/~ojw/NeedRender/?x=2002&y=1596&priority=1&src=InformationFreeway:mcknut&random=1193423153733
            var zf = mapviewer.getZoomFactor();
            var mt = mapviewer.getMapType();
            var proj = mt.getProjection();
            var pixel = proj.fromLatLonToPixel( pos, zf );
            var tile = mapviewer.map.coordToTile( pixel.x, pixel.y, zf, 256, 256 );
            tile.x = Math.floor( tile.x );
            tile.y = Math.floor( tile.y );
            var url = mt.getTileLayers()[0].getTileUrl( tile, zf );
            window.open( url );
            menu.remove();
        };
        menu.addItem( new MMMenuItem( 'View map tile', func, null, 11 ) );
        func = function() {
            var zf = mapviewer.getZoomFactor();
            var mt = mapviewer.getMapType();
            var proj = mt.getProjection();
            var pixel = proj.fromLatLonToPixel( pos, zf );
            var tile = mapviewer.map.coordToTile( pixel.x, pixel.y, zf, 256, 256 );
            tile.x = Math.floor( tile.x );
            tile.y = Math.floor( tile.y );
            var url = 'http://tah.openstreetmap.org/Browse/details/tile/'+(zf-1)+'/'+tile.x+'/'+tile.y+'/';
            //var url = 'http://tah.openstreetmap.org/Tiles/info.php?x='+tile.x+'&y='+tile.y+'&z='+(zf-1)+'&layer=tile';
            window.open(url );
            menu.remove();
        };
        menu.addItem( new MMMenuItem( 'Tile info', func, null, 12 ) );
    }
    menu.addItem( new MMMenuItem( 'Alert position', function() {
        alert( pos.toString() );
        }, null, 1 ) );
}

function locationUpdate( a, b, c, d ) {
    var bits = [];
    if( d.name )
        bits.push( d.name );
    if( d.admin1 )
        bits.push( d.admin1 );
    if( d.iso )
        bits.push( d.iso );
    var str = 'Map of '+bits.join( ', ' );
    try {
        document.title = str;
    } catch( e ) {
    }
}

function clearGeocodeMarkers() {
    while( geocode_markers.length ) {
        mapviewer.removeOverlay( geocode_markers.shift() );
    }
}

function endGeocode() {
    var rs = geocoder.result_set.concat();
    var marker, result;
    var bounds = new MMBounds()
    while( rs.length ) {
        result = rs.shift();
        marker = mapviewer.createMarker( result.coords, { 'label' : result.address.display_name } );
        marker.setAttribute( 'geocode_result', true );
        marker.setAttribute( 'zoom_factor', result.zoom_factor );
        bounds.extend( result.coords );
        geocode_markers.push( marker );
    }
    if( bounds.getSouthWest() )
        mapviewer.goToPosition( bounds );
    /*
    if( c ) {
        clearGeocodeMarker();
        geocode_marker = mapviewer.createMarker( c.coords, { 'label' : c.address.display_name } );
    }
*/
}

function handleQuery() {
    var location;
    var query = $('query');
    if( query )
        query = query.value;
    if( query && query != '' ) {
        var matches = query.match( /(-[0-9]+(\.[0-9]+)).*(-[0-9]+(\.[0-9]+)).*([0-9]+)?/ );
        if( ! matches )
            matches = query.match( /([0-9]+(\.[0-9]+)).*(-[0-9]+(\.[0-9]+)).*([0-9]+)?/ );
        if( ! matches )
            matches = query.match( /(-[0-9]+(\.[0-9]+)).*([0-9]+(\.[0-9]+)).*([0-9]+)?/ );
        if( ! matches )
            matches = query.match( /([0-9]+(\.[0-9]+)).*([0-9]+(\.[0-9]+)).*([0-9]+)?/ );
        if( matches ) {
            location = new MMLocation( new MMLatLon( Number( matches[1] ), Number( matches[3] ) ) );
            if( matches[5] != undefined )
                location.zoom_factor = matches[5];
        } else {
            clearGeocodeMarkers();
            // This logging is only here because I needed to test some logging
            // code, nothing nefarious.
            var i = new Image();
            i.src = 'http://'+window.location.host+'/map/log.php?q='+encodeURIComponent(query);
            var parts = query.split( ':' );
            geocoder.geocode( new MMAddress( { 'qs' : parts[0], 'country_code' : parts[1]} ) );
        }
    }
    if( location )
        mapviewer.goToPosition( location );
    return false;
}

function parseHash() {
    var hash = window.location.hash;
    var options = {}
    if( hash && hash != '' && hash != '#' ) {
        hash = hash.substring(1);
    } else if( document.cookie && document.cookie != '' ) {
        hash = String( document.cookie );
        hash = hash.replace( /; /g, '&' );
    }
    if( hash ) {
        var bits = hash.split( '&' );
        var kv, bit,  params = {};
        while( bits.length ) {
            var bit = bits.shift();
            if( bit ) {
                kv = bit.split( '=' );
                params[kv[0]] = decodeURIComponent(kv[1]);
            }
        }
        if( params['bb'] ) {
            var bb = params['bb'].split( ',' );
            options.location = new MMBounds(
                new MMLatLon( Number(bb[0]), Number(bb[1] ) ),
                new MMLatLon( Number(bb[2]), Number(bb[3] ) ) );
        } else if( params['lat'] && params['lon'] ) {
            options.location = new MMLatLon( params['lat'], params['lon'] );
        } else if( params['q'] ) {
            $('query').value = params['q'];
            options.location = params['q'];
        }
        if( params['mlat'] && params['mlon'] ) {
            options.marker = new MMLatLon( params['mlat'], params['mlon'] );
        }
        if( params['title'] ) {
            options.title = params['title'];
        }
        if( params['zf'] && ! ( options.location instanceof MMLocation ) ) {
            options.location = new MMLocation( options.location, Number( params['zf'] ) );
        }
        if( params['t'] ) {
            var mt, mts = mapviewer.getAvailableMapTypes();
            while( mts.length ) {
                mt = mts.shift();
                if( mt instanceof MMMapType ) {
                    if( params['t'] == mt.getUrlArg() ) {
                        options.map_type = mt;
                        break;
                    }
                } else {
                    if( Number( params['t'] ) == mt ) {
                        options.map_type = mt;
                        break;
                    }
                }
            }
        }
        if( params['s'] ) {
            options.scene = params['s'];
        }
    }
    if( ! options.location ) {
        options.location = new MMBounds( new MMLatLon( -85, -180 ), new MMLatLon( 85, 180 ) );
    }
    return options;
}

var first = true;

function updateHash() {
    var hash = '';
    var mt = mapviewer.getMapType();
    if( mt instanceof MMMapType ) {
        mt = mt.getUrlArg();
    }
    var pos = mapviewer.getCurrentPosition();
    var zf = mapviewer.getZoomFactor();
    if( first ) {
        first = false;
    } else {
        if( options.title )
            hash += 'title='+encodeURIComponent(options.title)+'&';
        if( options.marker )
            hash += 'mlat='+options.marker.lat+'&mlon='+options.marker.lon+'&';
        hash += 't='+mt;
        createCookie( 't', mt, 100 );
        hash += '&lat='+pos.lat+'&lon='+pos.lon;
        createCookie( 'lat', pos.lat, 100 );
        createCookie( 'lon', pos.lon, 100 );
        hash += '&zf='+zf;
        createCookie( 'zf', zf, 100 );
        if( mt == MM_WORLD_BIRDSEYE || mt == MM_WORLD_BEHYBRID ) {
            var scene = mapviewer.getBirdsEyeScene();
            if( scene ) {
                hash += '&s='+scene.id;
                createCookie( 's', scene.id, 100 );
            }
        } else {
            createCookie( 's', '', 100 );
        }
        window.location.hash = hash;
    }

    var url = 'http://www.multimap.com/maps/#t=l&map='+pos.lat+','+pos.lon+'|'+zf+'|'+mt;
    $('multimapad').firstChild.href = url;

    url = 'http://www.openstreetmap.org/edit.html?lat='+pos.lat+'&lon='+pos.lon+'&zoom='+(zf-1);
    $('editlink').href = url;
}

function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

onLoad();
window.onload = function() {
    setInterval(function() {
        window.scrollTo(0, 1);
    }, 100);
}
