﻿/// <reference path="js/OpenLayers/lib/OpenLayers.js" />

// Map functions extented for OpenLayers
//var lon = 5;
//var lat = 40;
//var zoom = 12;
var kmlFile = "kml/MRD_Articles_20090706_OL.kml";
//var kmlFile = "kml/Articles20090622.kml";
var map, panel, select, selArt, mrdArticles, popup;
var layers = Array();
var selFeatures = new Array();
var selFeatureIds = new Array();

var webMapCallback = "";
var timerInterval = 2000;
var wait;
var firstTime = true;

AutoSizeFramedCloud = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
    'autoSize': true
});

OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";


// Initialize Map and load KML cotainig articles
function init(){

    var options = {
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG:4326"),
        units: "m",
        numZoomLevels: 22,
        maxResolution: 156543.0339,
        maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
        controls: [ 
           new OpenLayers.Control.PanZoomBar(),
           new OpenLayers.Control.LayerSwitcher({'ascending':false}),
           new OpenLayers.Control.MousePosition(),
           new OpenLayers.Control.KeyboardDefaults()
        ]
    };

    // create map
    map = new OpenLayers.Map('map',options);
    
    // create Google Mercator layers
    // Load Google Layers
    var gphy = new OpenLayers.Layer.Google(
        "Google Physical",
        {type: G_PHYSICAL_MAP,
        'sphericalMercator': true,
        numZoomLevels: 22}
    );
//    var gmap = new OpenLayers.Layer.Google(
//        "Google Streets",
//        {'sphericalMercator': true, numZoomLevels: 22}
//    );
//    var gsat = new OpenLayers.Layer.Google(
//        "Google Satellite",
//        {type: G_SATELLITE_MAP, 'sphericalMercator': true, numZoomLevels: 22}
//    );
//    var ghyb = new OpenLayers.Layer.Google(
//        "Google Hybrid",
//        {type: G_HYBRID_MAP, 'sphericalMercator': true, numZoomLevels: 22}
//    );

    // create MRD articles layer
    mrdArticles = new OpenLayers.Layer.Vector("MRD Articles", {
        projection: map.displayProjection,
        strategies: [
            new OpenLayers.Strategy.Fixed()
        ],
        protocol: new OpenLayers.Protocol.HTTP({
            url: kmlFile,
            format: new OpenLayers.Format.KML({
                extractStyles: true,
                extractAttributes: true
            })
        })
    });
    
    layers[0] = mrdArticles;

    //map.addLayers([mrdArticles, gphy, gmap, gsat, ghyb]);
    map.addLayers([mrdArticles, gphy]);
    
    // Add previous next buttons
    nav = new OpenLayers.Control.NavigationHistory();
    nav.next.title = "Go to next extent";
    nav.previous.title = "Go to previous extent";
    // parent control must be added to the map
    map.addControl(nav);
    
    // create zoombox
    zb = new OpenLayers.Control.ZoomBox(
        {title:"Zoom on an area by clicking and dragging."});           
    
    selArt = new OpenLayers.Control.SelectFeature(
        mrdArticles,
        {
            clickout: true, toggle: false,
            multiple: true, hover: false,
            toggleKey: "ctrlKey", // ctrl key removes from selection
            multipleKey: "shiftKey", // shift key adds to selection
            box: true,
            title:'Select articles by clicking or dragging a rectangle.'
        }
    ),
    

    panel = new OpenLayers.Control.Panel(
        {'div': OpenLayers.Util.getElement('MapToolbar'), defaultControl: zb}
    );
    panel.addControls([new OpenLayers.Control.MouseDefaults(
        {title:'Pan the map by clicking and dragging.'}),
        zb, selArt,
        nav.next, nav.previous
    ]);

    
    map.addControl(panel);
    
    mrdArticles.events.on({
        "featureselected": onFeatureSelect,
        "featureunselected": onFeatureUnselect
    });
    

    //map.addControl(select);
    //select.activate();
    //selArt.activate();
    
    
    // left, bottom, right, top
    //map.setCenter(new OpenLayers.LonLat(10.205188,48.857593), 4);
//    var proj = new OpenLayers.Projection("EPSG:4326");
//    var point = new OpenLayers.LonLat(-71, 42);
//    point.transform(proj, map.getProjectionObject());
//    map.setCenter(point);

//    var bounds = new OpenLayers.Bounds(-74.047185, 40.679648, -73.907005, 40.882078)
//    bounds.transform(proj, map.getProjectionObject());


    map.zoomToExtent(new OpenLayers.Bounds(
 	    68.774414, 11.381836, 123.662109, 34.628906
 	    ).transform(map.displayProjection, map.projection)
    );
    if (!map.getCenter()) {map.zoomToMaxExtent()}
    
    
    // HACK HACK don't know how to chnge it by css
    // change size of MaximizeDiv
    var lyrSwitcherDiv = document.getElementById('OpenLayers_Control_MaximizeDiv');
    lyrSwitcherDiv.style.height = "25px";
    lyrSwitcherDiv.style.width = "25px";
    
    var lyrSwitcherImg = document.getElementById('OpenLayers_Control_MaximizeDiv_innerImage');
    lyrSwitcherImg.style.height = "25px";
    lyrSwitcherImg.style.width = "25px";
    lyrSwitcherImg.src = "js/Openlayers/theme/natural/img/layer-switcher-maximize.gif"
}


function update() {
    var clickout = document.getElementById("clickout").checked;
    drawControls.select.clickout = clickout;
    drawControls.select.box = document.getElementById("box").checked;
    if(drawControls.select.active) {
        drawControls.select.deactivate();
        drawControls.select.activate();
    }
}


function onPopupClose(evt) {
    closePopup();
}

// User selected features
function onFeatureSelect(event) {
    // add feature to array
    selFeatureIds.push(event.feature.attributes.name);
    selFeatures.push(event.feature);
    
    // call function to show selected features in table
    // after all features where selected
    clearInterval(wait); // clear old intervals
    wait = setTimeout("showSelectedInTable()", 500);
    
    selArt.unselect(event.feature);
}

// get selected features in fo from database and show it in the map
// call server for that
function showSelectedInTable() {
    // clear timeout
    clearInterval(wait);
    
    //if (selFeatures.length == 1) {
        // open popup of first feature found
        openPopup(selFeatures[0]);
    //}
    // postback to execute serverside function
    var argument = "ControlType=Map&EventArg=" + selFeatureIds.toString();
    
    CallServer(argument, '');
    
    // update updatePanel to show table
    setTimeout("__doPostBack(UpdatePanelId, '')", 500);
    
    
    // HACK do a second postback first time, 
    // otherwise table will not show up
//    if(firstTime) {
//        __doPostBack(UpdatePanelId,'');
//        firstTime = false;
//    }
    
    selFeatureIds = new Array();
    selFeatures = new Array();
}

function onFeatureUnselect(event) {
    var feature = event.feature;
    if(feature.popup) {
        map.removePopup(feature.popup);
        feature.popup.destroy();
        delete feature.popup;
    }
}

// Zoom to selected features in array
function zoomToSelectedFeatures(features) {
    
    if (features.length > 0) {
        var bounds = features[0].geometry.getBounds().clone();
        for (var i = 1; i < features.length; i++) {
            bounds.extend(features[i].geometry.getBounds());
        }
        map.zoomToExtent(bounds, false);
    }
}

function zoomToSelectedFeature(id) {
    var feature = getFeatureByName(id);
    zoomToFeature(feature);
}

function zoomToFeature(feature) {
    if (feature) {
        var bounds = feature.geometry.getBounds().clone();
        var boundPrj = bounds.transform(map.displayProjection, map.projection);
        map.setCenter(boundPrj.getCenterLonLat(), 7, false, false);
//        map.zoomToExtent(), false);
//        map.zoomTo(7);
        //map.zoomToExtent(bounds, false);
        openPopup(feature);
    }
}

// returns a feature identified by name
function getFeatureByName(id) {
    var feat;
    for (var i = 0; i < mrdArticles.features.length; i++) {
        if(mrdArticles.features[i].attributes.name == id) {
            return mrdArticles.features[i];
        }
    }
    return null;
}

// opens popup from feature by id
function openPopup(feature) {

    // close previously opened popups
    closePopup();

    if(feature) {
        // Since KML is user-generated, do naive protection against
        // Javascript.
        var content = "";
        
        var attrVal = feature.attributes.description.split('&');
        var attrValCol = new Hashtable();
        var keyVal;
        var key;
        var value;

        for (var i=0;i<attrVal.length;i=i+1)
        {
            keyVal = attrVal[i].split('%');
            attrValCol.put(keyVal[0], keyVal[1]);
        }
        
        // write html table
        var table = writePopupTable(attrValCol);
        
        if (content.search("<script") != -1) {
            content = "Content contained Javascript! Escaped content below.<br />" + content.replace(/</g, "&lt;");
        }
        popup = new AutoSizeFramedCloud("info", 
             feature.geometry.getBounds().getCenterLonLat(),
             new OpenLayers.Size(200,100),
             table,
             null, true, onPopupClose);
        feature.popup = popup;
        map.addPopup(popup);

    }
}

// Write HTML table for popup
function writePopupTable(attrValCol) {
    
    var table;
    
    table =
    "<table border='0' cellpadding='0' cellspacing='0' width='400' style='font-size: 11px;" +
        "font-family: Verdana, Arial, Helvetica, sans-serif; padding: 2px 2px 2px 5px;" +
        "margin-top: 5px; vertical-align: top;'>" +
        "<tr>" +
            "<td colspan='2' style='padding: 1px 2px 10px 3px;'>" +
            "<font color='#CC0033'><b>" + attrValCol.get('TITLE') + "</b></font></td>" +
        "</tr>";
    
    table = table + addTableRow("AUTHORS", attrValCol.get('AUTHORS'));
    table = table + addTableRow("ABSTRACT", attrValCol.get('ABSTRACT'));
    table = table + addTableRow("YEAR", attrValCol.get('PY'));
    table = table + addTableRow("VOLUME", attrValCol.get('VOLUME'));
    table = table + addTableRow("ISSUE", attrValCol.get('ISSUE'));
    table = table + addTableRow("PAGE RANGE", attrValCol.get('BP') + " - " + attrValCol.get('EP'));
    table = table + addTableRow("URL", "<a href='" + attrValCol.get('URL') + "'>" + attrValCol.get('URL') + "</a>" );
        
    table = table + "</table>";
    
    return table;

}

// Add row to table
function addTableRow(key, val) {

    var row = 
        "<tr style='vertical-align: top;'>" +
            "<td bgcolor='#FFFFFF' align='right' style='padding: 1px 2px 2px 3px;'>" +
            "<font color='#757575'><b>" + key + ":</b></font></td>" +
            "<td bgcolor='#FFFFFF' style='padding: 1px 2px 2px 3px;'>" +
                "<font color='#757575'>"+ val + "</font></td>" +
        "</tr>";

    return row;
}


// close feature ballon
function closePopup() {
    if(popup) {
        map.removePopup(popup);
//        popup.destroy();
//        //delete popup;
//        popup = null;
        //popup.destroy();
    }
}

// -----------------------

function addAnchor() { 
     popup = new OpenLayers.Popup.Anchored("chicken",  
        new OpenLayers.LonLat(5,40), 
        new OpenLayers.Size(200,200), 
        "example popup", true); 
  
     map.addPopup(popup); 
}

    
function addMarker() { 

    markers = new OpenLayers.Layer.Markers("zibo"); 
    map.addLayer(markers); 

    feature = new OpenLayers.Feature(layer,  
                                        new OpenLayers.LonLat(0,0)); 


    marker = feature.createMarker(); 
     
     markers.addMarker(marker); 
    marker.events.register("mousedown", marker, mousedown); 
                                                       
 } 


// ----------------------


function mousedown(evt) { 
    // check to see if the popup was hidden by the close box 
    // if so, then destroy it before continuing 
    if (popup != null) { 
        if (!popup.visible()) { 
            markers.map.removePopup(popup); 
            popup.destroy(); 
            popup = null; 
        } 
    } 
    OpenLayers.Event.stop(evt); 
}     





//object selection function
//
//when the user click on the map the function returns the selected 
//geometry objects
//for polygons I use pointInPolygon
//for path I use lineDist
//for points ... nothing but it's simple to add
function objectSelection(evt) {

    //if (!document.getElementById('selectToggle').checked) return;

    var fout = Array();
    var lonlat = map.getLonLatFromViewPortPx(evt.xy);
    var mousePoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);

    for (var i = 0; i < layers.length; i++) {

        var features = layers[i].features;
        for (var f = 0; f < features.length; f++) {
            //var the_geom = features[f].geometry.toString();

//            if (the_geom.indexOf('POLYGON') != -1) {
//                if (pointInPolygon(the_geom,lonlat)) {
//                    fout.push(features[f]);
//                }
//            }
//            else {
//                if (lineDist(the_geom,lonlat) <= 10) {
//                    fout.push(features[f]);
//                }
//            }
            var dist = pointDist(features[f], mousePoint);
            if (dist <= 0.01) {
                alert(dist);
                fout.push(features[f]);
            }
        }
    }

    if (fout.length > 0 ){
    for (k = 0; k < fout.length; k++) {
        var feature = fout[k];
        var layer = feature.layer;

        if(OpenLayers.Util.indexOf(layer.selectedFeatures, feature) > -1) {
            if(feature.originalStyle != null) {
                feature.style = feature.originalStyle;
            }

            layer.drawFeature(feature);
            OpenLayers.Util.removeItem(layer.selectedFeatures, feature);
            //onFeatureUnselect(feature);
        } else {
            if(feature.originalStyle == null) {
                feature.originalStyle = feature.style;
            }
            feature.layer.selectedFeatures.push(feature);
            feature.style = OpenLayers.Feature.Vector.style['select'];
            feature.layer.drawFeature(feature);
            //onFeatureSelect(feature);
        }
    }
    
    zoomToSelectedFeatures(fout);
    if (fout.length < 2) {
        openPopup(fout[0]);
    }
    } else {
        closePopup();
    }
}


function pointDist(point, mousePoint) {
    
    var dist = point.geometry.distanceTo(mousePoint);
    return dist;
}


//compute the point-line distance
function lineDist(wktline, _p) {

    var p1x = Array();
    var p1y = Array();
    var p2x = Array();
    var p2y = Array();

    var _tmp = wktline.substring(11,wktline.length-1).split(","); //point list
    var p = map.getPixelFromLonLat(_p);

    for (var k = 0; k < _tmp.length - 1; k++) {
        var p1xy = _tmp[k].split(" ");
        var p2xy = _tmp[k+1].split(" ");

        var _point1 = new OpenLayers.LonLat(p1xy[0],p1xy[1]);
        var _point2 = new OpenLayers.LonLat(p2xy[0],p2xy[1]);

        var p1 = map.getPixelFromLonLat(_point1);
        var p2 = map.getPixelFromLonLat(_point2);

        p1x.push(p1.x);p1y.push(p1.y);
        p2x.push(p2.x);p2y.push(p2.y);
    }

    var dist = -1;
    for (var k = 0; k < p1x.length; k++) {
        var area = Math.abs(.5 * (p1x[k] * p2y[k] + p2x[k] * p.y + p.x * p1y[k] - p2x[k] * p1y[k] - p.x * p2y[k] - p1x[k] * p.y));
        var bottom = Math.sqrt(Math.pow(p1x[k] - p2x[k], 2) + Math.pow(p1y[k] - p2y[k], 2));

        if (dist == -1) 
                dist = (area / bottom * 2);
        else
                dist = Math.min((area / bottom * 2),dist);
    }

    return dist;
}


//point inside polygon algorithm
function pointInPolygon(wktpoly,ll) {

  var x = ll.lon;
  var y = ll.lat;

  var _tmp = wktpoly.substring(9,wktpoly.length-2).split(","); //point list
  var polySides = _tmp.length-1;

  var polyX = Array();
  var polyY = Array();

  for (var k = 0; k < polySides; k++) {
        var xy = _tmp[k].split(" ");
        polyX.push(parseFloat(xy[0]));
        polyY.push(parseFloat(xy[1]));
  }

  var      i,j;
  var      oddNodes=false   ;

  for (i=0,j=polySides-1; i<polySides; j=i++) {
    val = polyX[i]+(y-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i]);
    if (polyY[i]<y && polyY[j]>=y || polyY[j]<y && polyY[i]>=y) {
      if (polyX[i]+(y-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i])<x) {
        oddNodes=!oddNodes; 
      }
    }
  }

  return oddNodes; 
}


// receive callback result data from server
function ReceiveServerData(arg, context)
{

}
