﻿// JScript File

var Map = new Object();

// -----------------  Map Initialization Routines  ------------------------------
Map.initialize = function(latCenter, longCenter, zoomLevel, useSatellite)
{
    this.routes = new Array();
    this.markers = new Array();
    this.areas = new Array();
    this.center = new GLatLng(latCenter, longCenter);
    this.zoomLevel = zoomLevel;
    this.linesVisible = true;
    this.plineColor = '#593e20';  // default to brown color for map
    this.geocoder = null;

    this.googleMap = null;
    
    if (GBrowserIsCompatible())
    {
        var mapElement = document.getElementById('map_element')
        this.googleMap = new GMap2(mapElement);
        
        GEvent.addListener(this.googleMap, 'maptypechanged', function() { Map.setPLineColor(); });

        if (zoomLevel > 0)
            Map.reset();

        if (useSatellite)
            this.googleMap.setMapType(G_SATELLITE_MAP);

        var resetOutline = document.createElement('div');
        resetOutline.className = 'resetOuter';
        resetOutline.title = 'Reset Map';
        resetOutline.onclick = callReset;
        if (resetOutline.captureEvents) resetOutline.captureEvents(Event.CLICK);
        
        var resetButton = document.createElement('div');
        resetButton.className = 'resetInner';
        resetButton.innerHTML = 'Reset';
        
        resetOutline.appendChild(resetButton);
        mapElement.appendChild(resetOutline);
    }
    else
    {
        hide('map_element');
        hide('resetOutline');
    }
};

Map.setCoords = function(north, east, south, west)
{
    this.zoomLevel = this.googleMap.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(south,west), new GLatLng(north,east)));
    if (this.zoomLevel > 12) this.zoomLevel = 12;  // don't zoom in too much, which can happen if you only have one point on the map
    
    this.center = new GLatLng((north + south) / 2, (east + west) / 2);
    
    Map.reset();
};

Map.isCompatible = function()
{
    return GBrowserIsCompatible();
};

Map.reset = function()
{
    // center map
    this.googleMap.setCenter(this.center, this.zoomLevel);
    
    // show "map" type (as opposed to satellite imagery)
    this.googleMap.setMapType(G_NORMAL_MAP);
    
    // show route (in case hidden)
    if (!this.linesVisible)
        toggleLines();
};

Map.enable = function()
{
    this.showPolylines();
    this.showPolygons();
    this.showMarkers();
    
    this.googleMap.setUIToDefault();
    this.googleMap.disableScrollWheelZoom();
};

Map.search = function(searchValue, returnFunction)
{
    if (!Map.geocoder) Map.geocoder = new GClientGeocoder();
    Map.geocoder.getLatLng(searchValue, returnFunction);
};

Map.setCenter = function(point, zoomLevel)
{
    this.center = point;
    this.zoomLevel = zoomLevel;
    Map.reset();
};

Map.getCenter = function()
{
    return this.googleMap.getCenter();
};

Map.getZoomLevel = function()
{
    return this.googleMap.getZoom();
};

function toggleLines()
{
    var link = document.getElementById('toggleLink');
    if (Map.linesVisible)
    {
        link.innerHTML = 'Show Route';
        Map.hidePolylines();
        Map.hidePolygons();
    }
    else
    {
        link.innerHTML = 'Hide Route';
        Map.showPolylines();
        Map.showPolygons();
    }
    
    Map.linesVisible = !Map.linesVisible;
}

// -------------  Index Links  ------------------------------------

Map.createIndexHtml = function(states, railroads, wrap)
{
    var indexSpan = document.createElement('div');
    if (states.length > 0 || railroads.length > 0)
    {
        indexSpan.className = 'footnote';
        
        if (states.length > 0)
        {
            var statesLabel = document.createTextNode('States:');
            var statesBolder = document.createElement('strong');
            statesBolder.appendChild(statesLabel);
            indexSpan.appendChild(statesBolder);
            indexSpan.appendChild(document.createTextNode(' '));
            
            indexSpan.appendChild(Map.createIndexLink(states[0]));
            
            for(var i = 1; i < states.length; i++)
            {
                indexSpan.appendChild(document.createTextNode(', '));
                indexSpan.appendChild(Map.createIndexLink(states[i]));
            }
        }
        
        if (railroads.length > 0)
        {
            if (states.length > 0)
            {
                if (wrap)
                    indexSpan.appendChild(document.createElement('br'));
                else
                    indexSpan.appendChild(document.createTextNode(' | '));
            }
                
        
            var rrLabel = document.createTextNode('Railroads:');
            var rrBolder = document.createElement('strong');
            rrBolder.appendChild(rrLabel);
            indexSpan.appendChild(rrBolder);
            indexSpan.appendChild(document.createTextNode(' '));
            
            indexSpan.appendChild(Map.createIndexLink(railroads[0]));
        
            for(var j = 1; j < railroads.length; j++)
            {
                indexSpan.appendChild(document.createTextNode(', '));
                indexSpan.appendChild(Map.createIndexLink(railroads[j]));
            }
        }
    }
    return indexSpan;
};

Map.createIndexLink = function(indexObj)
{
    var link = document.createElement('a');
    link.href = indexObj.filename;
    link.title = indexObj.name;
    link.appendChild(document.createTextNode(indexObj.abbreviation));
    return link;
};

Map.padNumber = function(number, length)
{
    var result = number.toString();
    while (result.length < length)
    {
        result = '0' + result;
    };
    return result;
};

// -------------  Abandonments  ------------------------------------

Map.addAbandonment = function(latitude, longitude, highlighted, endpoints, name, filename, iconFlags, states, railroads)
{
    var point = new GLatLng(latitude, longitude);
    var marker;
    if (highlighted)
        marker = Map.addMarker(point, 'white');
    else
        marker = Map.addMarker(point, 'blue');
    
    GEvent.addListener(marker, 'click', function() { Map.showAbandonment(point, endpoints, name, filename, iconFlags, states, railroads); });
    
    this.markers[this.markers.length] = marker;
};

Map.showAbandonment = function(point, endpoints, name, filename, iconFlags, states, railroads)
{
    Map.showInfo(point, Map.createAbandonmentMarkerHtml(endpoints, name, filename, iconFlags, states, railroads));
};

Map.createAbandonmentMarkerHtml = function(endpoints, name, filename, iconFlags, states, railroads)
{
    var link = document.createElement('a');
    link.href = filename;
    link.innerHTML = endpoints;
    
    var para = document.createElement('p');
    para.appendChild(link);
    if (name && name.length > 0)
    {
        para.appendChild(document.createElement('br'));
        var em = document.createElement('em');
        em.appendChild(document.createTextNode(name));
        para.appendChild(em);
    }
    
    para.appendChild(Map.createIndexHtml(states, railroads, true));

    var iconDiv = document.createElement('div');
    if (iconFlags == 0)
        iconDiv.appendChild(Map.createAbandonmentIcon('unknown.png', 'Information is needed for this abandoned route.'));
    if (iconFlags & 1)
        iconDiv.appendChild(Map.createAbandonmentIcon('text.png', 'This abandoned route has historical information.'));
    if (iconFlags & 2)
        iconDiv.appendChild(Map.createAbandonmentIcon('map.png', 'This abandoned route has a map.'));
    if (iconFlags & 4)
        iconDiv.appendChild(Map.createAbandonmentIcon('camera.png', 'This abandoned route has associated pictures.'));
    if (iconFlags & 8)
        iconDiv.appendChild(Map.createAbandonmentIcon('filing.png', 'This abandoned route has associated ICC filings.'));
    
    var container = document.createElement('div');
    container.appendChild(para);
    container.appendChild(iconDiv);
    return container;
};

Map.createAbandonmentIcon = function(filename, alt)
{
    var icon = document.createElement('img');
    icon.src = 'resources/icons/' + filename;
    icon.alt = alt;
    icon.style.marginRight = '8px';
    return icon;
};

// -------------  Polylines  ---------------------------------------
Map.addPolyline = function(levelCount, encodedPoints)
{
    Map.addEncodedPolyline(encodedPoints, Map.getZoomLevels(levelCount));
};

Map.addEncodedPolyline = function(encodedPoints, encodedLevels)
{
    var polyline = new GPolyline.fromEncoded(
    {
        color: this.plineColor,
        weight: 7,
        points: encodedPoints,
        levels: encodedLevels,
        zoomFactor: 32,
        numLevels: 4,
        opacity: 0.75
    });
    
    this.routes[this.routes.length] = polyline;
};

Map.showPolylines = function()
{
    for (var i = 0; i < this.routes.length; i++)
        this.googleMap.addOverlay(this.routes[i]);
};

Map.hidePolylines = function()
{
    for (var i = 0; i < this.routes.length; i++)
        this.googleMap.removeOverlay(this.routes[i]);
};

Map.getZoomLevels = function(levelCount)
{
    var zoomLevel = 'B';
    var levels = new String();
    
    for(var i = 0; i < levelCount; i++)
        levels += zoomLevel;
    
    return levels;
};

Map.setPLineColor = function()
{
    var mapType = this.googleMap.getCurrentMapType();

    // determine what color to use based on map type
    switch (mapType)
    {
        case G_NORMAL_MAP:
            this.plineColor = '#593e20';  // use default brown color for maps
            break;
        case G_SATELLITE_MAP:
        case G_HYBRID_MAP:
            this.plineColor = '#e8e8e8';  // use light-gray color for satellite imagery
            break;
    }
    
    // loop through each PLine and set its color
    for (var i = 0; i < this.routes.length; i++)
    {
        // remove the overlay
        this.googleMap.removeOverlay(this.routes[i]);
    
        // change to the new color
        this.routes[i].color = this.plineColor;
        
        // redisplay the pline so new color takes affect
        this.googleMap.addOverlay(this.routes[i]);
    }
    
};

// -------------------  Polygons (Map)  -------------------------------------------
Map.addPolygon = function (levelCount, encodedPoints)
{
     Map.addEncodedPolygon(encodedPoints, Map.getZoomLevels(levelCount));
};

Map.addEncodedPolygon = function(encodedPoints, encodedLevels)
{
     var polygon = new GPolygon.fromEncoded(
     {
        polylines:
        [{
            color: '#000000',
            weight: 3,
            points: encodedPoints,
            levels: encodedLevels,
            zoomFactor: 16,
            numLevels: 4,
            opacity: 0.25
        }],
        fill: true,
        color: this.plineColor,
        opacity: 0.45,
        outline: true
     });
     
     this.areas[this.areas.length] = polygon;
};

Map.showPolygons = function()
{
    for (var i = 0; i < this.areas.length; i++)
        this.googleMap.addOverlay(this.areas[i]);
};

Map.hidePolygons = function()
{
    for (var i = 0; i < this.areas.length; i++)
        this.googleMap.removeOverlay(this.areas[i]);
};

// -----------------  Photos (Map)  --------------------------------------------------
Map.addPhotos = function(latitude, longitude, photoIds)
{
    var point = new GLatLng(latitude, longitude);
    var marker = Map.addMarker(point, 'blue');
    
    GEvent.addListener(marker, 'click', function() { Map.showPhotos(point, photoIds); });
    
    this.markers[this.markers.length] = marker;
};

//Map.showPhoto = function(point, photoId, pictureOrderId, fileName, caption)
//{
//    // record a view of photo
//    recordData('type=mp&id=' + photoId);
//    
//    // show photo
//    Map.showInfo(point, Map.createPhotoMarkerHtml(pictureOrderId, fileName, caption));
//};

Map.showPhotos = function(point, photoIds)
{
    // record a view of the photos
    // ???
    
    // show photo
    Map.showInfo(point, Map.createHtmlForPhotos(photoIds));
};

Map.createHtmlForPhotos = function(photoIds)
{
    var photoTable = document.createElement('table');
    photoTable.border = '0';
    photoTable.cellSpacing = '0';
    photoTable.cellPadding = '2';
    photoTable.className = 'imagetable';
    
    var photoTableBody = document.createElement('tbody');
        
    var hasCaption = false;
    
    var photos = new Array();
    var counter = 0;
    for(var j = 0; j < photoIds.length; j++)
    {
        var photo = slideshow.findPhoto(photoIds[j]);
        if (photo && counter++ < 3)  // only add first three photos
            photos[photos.length] = photo;
    }

    if (photos.length > 0)
    {    
        for (var i = 0; i < photos.length; i++)
        {
            var photo = eval(photos[i]);
        
            var imgElement = document.createElement('img');
            imgElement.src = 'http://abandonedrails.com/image.ashx?file=' + photo.filename + '&size=thumb';
            imgElement.style.border = '0px';

            var imageCell = document.createElement('td');
            imageCell.className = 'imagecell';
            imageCell.appendChild(imgElement);
            
            var captionCell = document.createElement('td');
            captionCell.className = 'captioncell';
            hasCaption = hasCaption || photo.caption != '';
            captionCell.innerHTML = photo.caption;
            
            var row = document.createElement('tr');
            row.appendChild(imageCell);
            row.appendChild(captionCell);
            photoTableBody.appendChild(row);
        }
    }
    photoTable.appendChild(photoTableBody);
    
    var container = document.createElement('div');
    container.className = 'imagemarkerdiv';
    
    container.appendChild(photoTable);
    
    if (!hasCaption)
    {
        // default width for photo container, as specified in CSS file, is 300 px. This includes size for caption
        // if caption not included, resize container div to fit just the picture
        container.style.width = '200px';
    }
    
    return container;
};

//Map.createPhotoMarkerHtml = function(pictureOrderId, fileName, caption)
//{
//    var photo = document.createElement('img');
//    photo.src = 'http://abandonedrails.com/image.ashx?file=' + fileName + '&size=thumb';
//    photo.style.border = '0px';

//    var photoLink = document.createElement('a');
//    photoLink.href = 'picture.asp?po=' + pictureOrderId.toString();
//    
//    photoLink.appendChild(photo);

//    var photoTableBody = document.createElement('tbody');
//    
//    var row = document.createElement('tr');
//    var cell = document.createElement('td');
//    cell.className = 'imagecell';
//    
//    cell.appendChild(photoLink);
//    row.appendChild(cell);
//    photoTableBody.appendChild(row);
//    
//    var photoTable = document.createElement('table');
//    photoTable.border = '0';
//    photoTable.cellSpacing = '0';
//    photoTable.cellPadding = '2';
//    photoTable.className = 'imagetable';
//    photoTable.appendChild(photoTableBody);
//    
//    var container = document.createElement('div');
//    container.className = 'imagemarkerdiv';
//    
//    container.appendChild(photoTable);
//    
//    if (caption != '')
//    {
//        var photoCaption = document.createElement('p');
//        photoCaption.className = 'footnote';
//        photoCaption.innerHTML = caption;

//        container.appendChild(photoCaption);
//    }
//    else
//    {
//        // default width for photo container, as specified in CSS file, is 300 px. This includes size for caption
//        // if caption not included, resize container div to fit just the picture
//        container.style.width = '200px';
//    }
//    
//    return container;
//};

// -----------------  Point of Interest Markers  ---------------------------------

Map.addPointMarker = function(id, latitude, longitude, name)
{
    var point = new GLatLng(latitude, longitude);
    var marker = Map.addMarker(point, 'red');
    
    GEvent.addListener(marker, 'click', function() { Map.showPoint(point, name, id); });
    
    this.markers[this.markers.length] = marker;
};

Map.showPoint = function(point, name, id)
{
    // show point of interest on map
    Map.showInfo(point, Map.createPointMarkerHtml(name, id));
};

Map.createPointMarkerHtml = function(name, id)
{
    var para = document.createElement('p');
    para.innerHTML = name;
    
    var container = document.createElement('div');
    container.appendChild(para);
    container.style.maxWidth = '350px';
    
    if (id && id != 0)
    {
        var viewId = document.createElement('p');
        viewId.className = 'footnote';
        viewId.innerHTML = id;
        container.appendChild(viewId);
    }
    
    return container;
};

// -------------------  TOWERS  -------------------------------------------
Map.addTowerMarker = function(latitude, longitude, towerNumber, towerName, location, notes, type, authorized, retired, isApproximate, isUnknown, linkNumber, railroads)
{
    var point = new GLatLng(latitude, longitude);
    var marker = Map.addMarker(point, 'orange');
    //Map.markers[Map.markers.length] = marker;
    
    GEvent.addListener(marker, 'click', function() { Map.showTowerInfo(point, towerNumber, towerName, location, notes, railroads, type, authorized, retired, isApproximate, isUnknown, linkNumber); });
    this.googleMap.addOverlay(marker);
};

Map.showTowerInfo = function(point, towerNumber, towerName, location, notes, railroads, type, authorized, retired, isApproximate, isUnknown, linkNumber)
{
    Map.showInfo(point, Map.createTowerMarkerHtml(towerNumber, towerName, location, notes, railroads, type, authorized, retired, isApproximate, isUnknown, linkNumber));
};

Map.createTowerMarkerHtml = function(towerNumber, towerName, location, notes, railroads, type, authorized, retired, isApproximate, isUnknown, linkNumber)
{
    var title = document.createElement('h3');
    title.appendChild(document.createTextNode('Texas Interlocking Tower '));
    
    var nbr = towerNumber.toString();
    var link = 'http://www.towers.txrrhistory.com/' + Map.padNumber(linkNumber, 3) + '/' + Map.padNumber(linkNumber, 3) + '.htm'
    if (towerNumber == 0)
    {
        nbr = 'A';
        link = 'http://www.towers.txrrhistory.com/A/A.htm'
    }
    
    if (linkNumber == 0)
        title.appendChild(document.createTextNode(nbr));
    else
    {
        var towerLink = document.createElement('a');
        towerLink.href = link;
        towerLink.target = '_blank';
        towerLink.appendChild(document.createTextNode(nbr));
        title.appendChild(towerLink);
    }
    
    var text = document.createElement('p');
    text.innerHTML = 'Located at ' + towerName + ', TX';
    
    if (location != '')
    {
        text.appendChild(document.createElement('br'));
        text.appendChild(document.createTextNode('(' + location + ')'));
    }
    
    if (notes != '')
    {
        var descSpan = document.createElement('div');
        descSpan.className = 'footnote';
        descSpan.innerHTML = notes;
        
        text.appendChild(document.createElement('br'));
        text.appendChild(descSpan);
    }
    
    var infoTable = document.createElement('table');
    infoTable.style.border = '1px';
    infoTable.style.width = '100%';
    infoTable.style.marginLeft = '10px';
    infoTable.style.marginRight = '10px';
    
    var railroadsSpan = Map.createIndexHtml(new Array(), railroads, false);
    
    if (railroads.length > 0)
    {
        var rrLabel = document.createTextNode('Railroads:');
        var rrBolder = document.createElement('strong');
        rrBolder.appendChild(rrLabel);

        var indexSpan = document.createElement('span');
        indexSpan.appendChild(Map.createIndexLink(railroads[0]));
    
        for(var j = 1; j < railroads.length; j++)
        {
            indexSpan.appendChild(document.createTextNode(', '));
            indexSpan.appendChild(Map.createIndexLink(railroads[j]));
        }

        infoTable.appendChild(Map.createRowEntry(rrBolder, indexSpan));
    }
    
    if (type != '')
    {
        var typeLabel = document.createTextNode('Type:');
        var typeBolder = document.createElement('strong');
        typeBolder.appendChild(typeLabel);

        infoTable.appendChild(Map.createRowEntry(typeBolder, document.createTextNode(type)));
    }
    
    if (authorized != '')
    {
        var authLabel = document.createTextNode('Authorized:');
        var authBolder = document.createElement('strong');
        authBolder.appendChild(authLabel);

        infoTable.appendChild(Map.createRowEntry(authBolder, document.createTextNode(authorized)));
    }
    
    if (retired != '')
    {
        var retLabel = document.createTextNode('Retired:');
        var retBolder = document.createElement('strong');
        retBolder.appendChild(retLabel);

        infoTable.appendChild(Map.createRowEntry(retBolder, document.createTextNode(retired)));
    }
    
    var footer = document.createElement('p');
    footer.className = "footnote";
    
    if (isApproximate)
    {
        footer.appendChild(document.createTextNode('Approximate Location'));
    }
    else if (isUnknown)
    {
        footer.appendChild(document.createTextNode('Unknown Location'));
    }
    
    var container = document.createElement('div');
    container.style.width = '300px';
    container.appendChild(title);
    container.appendChild(text);
    container.appendChild(infoTable);
    if (isApproximate || isUnknown)
        container.appendChild(footer);
    
    return container;
};

Map.createRowEntry = function(column1Element, column2Element)
{
    var container1 = document.createElement('span');
    container1.className = 'footnote';
    container1.appendChild(column1Element);

    var container2 = document.createElement('span');
    container2.className = 'footnote';
    container2.appendChild(column2Element);

    var cell1 = document.createElement('td');
    cell1.style.width = '50px';
    cell1.style.textAlign = 'right';
    cell1.appendChild(container1);
    
    var cell2 = document.createElement('td');
    cell2.style.textAlign = 'left';
    cell2.appendChild(container2);
    
    var row = document.createElement('tr');
    row.appendChild(cell1);
    row.appendChild(cell2);
    
    return row;
};

// -----------------  Utility Functions  -----------------------------------------

Map.showMarkers = function()
{
    for (var i = 0; i < this.markers.length; i++)
        this.googleMap.addOverlay(this.markers[i]);
};

Map.showMarkersInView = function()
{
    // loop through markers and get upper/lower bounds
    var north = -90;  // set to minimum
    var east = -180;  // set to minimum
    var south = 90;  // set to maximum
    var west = 180;  // set to maximum
    
    for(var i = 0; i < this.markers.length; i++)
    {
        var marker = this.markers[i];
        var latlng = marker.getLatLng();

        if (latlng.lat() != 0 && latlng.lat() > north)
            north = latlng.lat();
        else if (latlng.lat() != 0 && latlng.lat() < south)
            south = latlng.lat();
        
        if (latlng.lng() != 0 && latlng.lng() > east)
            east = latlng.lng();
        else if (latlng.lng() != 0 && latlng.lng() < west)
            west = latlng.lng();
        
        this.googleMap.addOverlay(marker);
    }
    
    Map.setCoords(north, east, south, west);
};

Map.deleteMarkers = function()
{
    for(var i = 0; i < this.markers.length; i++)
        this.googleMap.removeOverlay(this.markers[i]);
    
    this.markers = new Array();
}

Map.showInfo = function(point, html)
{
    this.googleMap.openInfoWindowHtml(point, html);
};

Map.addMarker = function(point, color)
{
    var suffix;
    switch (color)
    {
        case 'gray':
            suffix = 'a';
            break;
        default:
            suffix = color[0];
            break;            
    }

    var path = 'images/marker_' + suffix + '.png'
    if (window.location.href.indexOf('admin') > 0)
        path = '../' + path;
        
    return this.createMarker(point, path);
};

Map.createMarker = function(point, imageFile)
{
    var markerIcon = new GIcon(G_DEFAULT_ICON);
    markerIcon.image = imageFile;
    markerIcon.iconSize = new GSize(12,20);
    markerIcon.shadowSize = new GSize(22, 20);
    markerIcon.iconAnchor = new GPoint(6, 20);
    markerOptions = { icon:markerIcon };
    
    return new GMarker(point, markerOptions);
};

Map.addDefaultMarker = function(point)
{
    var marker = new GMarker(point);
    this.googleMap.addOverlay(marker);
    return marker;
};

Map.removeDefaultMarker = function(marker)
{
    this.googleMap.removeOverlay(marker);
};

Map.centerOnMarkers = function(marker1, marker2)
{
    var latlng1 = marker1.getLatLng();
    var latlng2 = marker2.getLatLng();
    
    var lowerLat = latlng1.lat();
    var upperLat = latlng2.lat();
    if (upperLat < lowerLat)
    {
        var lat = upperLat;
        upperLat = lowerLat;
        lowerLat = lat;
    }
    
    var lowerLng = latlng1.lng();
    var upperLng = latlng2.lng();
    if (upperLng < lowerLng)
    {
        var lng = upperLng;
        upperLng = lowerLng;
        lowerLng = lng;
    }
    
    var center = new GLatLng((upperLat + lowerLat) / 2, (upperLng + lowerLng) / 2)
    var zoom = this.googleMap.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(lowerLat, lowerLng), new GLatLng(upperLat, upperLng)));
    
    Map.setCenter(center, zoom);
};

// --------------------  Picture Object  --------------------------

var Picture = function(photoId, pictureOrderId, fileName, caption, latitude, longitude)
{
    this.photoId = photoId;
    this.pictureOrderId = pictureOrderId;
    this.filename = fileName;
    this.caption = caption;
    this.latitude = latitude;
    this.longitude = longitude;
};

function callReset()
{
    // called from the Reset button
    Map.reset();
}