﻿//function loadjscssfile(filename, filetype) {
//    //http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
//    if (filetype == "js") { //if filename is a external JavaScript file
//        var fileref = document.createElement('script')
//        fileref.setAttribute("type", "text/javascript")
//        fileref.setAttribute("src", filename)
//    }
//    else if (filetype == "css") { //if filename is an external CSS file
//        var fileref = document.createElement("link")
//        fileref.setAttribute("rel", "stylesheet")
//        fileref.setAttribute("type", "text/css")
//        fileref.setAttribute("href", filename)
//    }
//    if (typeof fileref != "undefined")
//        document.getElementsByTagName("head")[0].appendChild(fileref)
//}
//if (typeof (VEMap) === "undefined") {
//    loadjscssfile("http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2", "js");
//}

var clust_ids_ar = new Array();

var clusterme;

function activate_clusters() {
	clusterme = 1;
}
this.activate_clusters = activate_clusters;

function RPMap(RPMOptions, callback) {
    // if user accidentally omits the new keyword, this will
    // silently correct the problem... otherwise "this" will be the context in which
    // RPMap is defined in.
    if (!(this instanceof RPMap))
        return new RPMap(RPMOptions, callback);
    
    var thisRPMapObject = this;
    var RPPropertyLayer = null;
    var RPSearchLayer = null;
    var searchLocation = null;
    var mVEMap = null;
    var warn = alert; //use alert for now.
    var DictionaryOfContexts = {};
    function GetDictionaryOfContexts() {
        return DictionaryOfContexts;
    }
    this.GetDictionaryOfContexts = GetDictionaryOfContexts;
    function GetSearchLocation() {
        return searchLocation;
    }
    this.GetSearchLocation = GetSearchLocation;

    function clusteringCallback(clusters) {
    	clust_ids_ar.length = 0;
    	
    	for (var i = 0; i < clusters.length; ++i) {

    		var cluster = clusters[i];
    		var clusterShape = cluster.GetClusterShape();

    		
    		//alert('here' + clusterShape.GetID());

    		//clusterShape.SetCustomIcon = "img src='../Resources/Images/GreenPin_wplus.png' />";
    		var curzoom = mVEMap.GetZoomLevel();

    		clusterShape.SetAltitude(i);
    		
    		clusterShape.SetTitle("#" + i);
    		clusterShape.SetDescription("This area has " + cluster.Shapes.length + " locations!");

    		var clust_indiv_ar = cluster.Shapes;
    		//var two_points_ar = new Array();

    		for (var j = 0; j < clust_indiv_ar.length; ++j) {
    			//var pointlatlon = clust_indiv_ar[j].GetPoints();
    			
    			//clust_topleft_ar[i] = clust_indiv_ar[j].GetPoints();

    			//clust_topright_ar[i] = clust_indiv_ar[j].GetPoints();

    			clust_ids_ar[i] = clust_ids_ar[i] + "," + clust_indiv_ar[j].GetID();
    			
    			//two_points_ar[j] = clust_indiv_ar[0].GetPoints();

    		}
    		    
    		    //clust_ar[i] = two_points_ar;
    		
    		//two_points_ar[0] = new VELatLong(nh_maxmin_ar[1], nh_maxmin_ar[2], 0); 
    		
    	}
    }


    
    function AddContext(contextName) {
    	
    	var layer = new VEShapeLayer();

    	var options = new VEClusteringOptions();
    	options.Callback = clusteringCallback;
    	var customIcon = new VECustomIconSpecification();
    	//customIcon.Image = "../Resources/Images/GreenPin_wplus.png";
    	customIcon.CustomHTML = "<img class='clust_pin' src='../Resources/Images/GreenPin_wplus.png' />";
    	options.Icon = customIcon;

    	
    	//shapeLayer.SetClusteringConfiguration(VEClusteringType.Grid, options);
    	if (clusterme != null) {
    		if (clusterme == 1) {
    			layer.SetClusteringConfiguration(VEClusteringType.Grid, options);
    		}
    	}
    	
        mVEMap.AddShapeLayer(layer);
        var context = {
            contextName: contextName,
            pindictionary: {},
            layer: layer,
            IsPopulated : false,
            GetKeyFromShapeIndex: function(shape, index) { return contextName + "," + index; }
            //optional MakeIconFromShapeIndex: function(shape, index) {... }
            //optional MakeIconHtmlFromShapeIndex: function(shape, index) {... }
        }
        DictionaryOfContexts[contextName] = context;
        return context;
    }
    this.AddContext = AddContext;
    function ExtendContext(contextName, extension) {
        return $.extend(DictionaryOfContexts[contextName], extension);
    }
    this.ExtendContext = ExtendContext;
    function AddAndExtendContext(contextName, extension) {
        AddContext(contextName);
        return ExtendContext(contextName, extension);
    }
    this.AddAndExtendContext = AddAndExtendContext;
    function GetSiteContext() {
        return DictionaryOfContexts.Sites;
    }
    function GetPropertyLayer() {
        return DictionaryOfContexts.Sites.layer;
    }
    function SetPropertyLayer( layer ) {
        DictionaryOfContexts.Sites.layer = layer;
    }

    var SavedAddress = "";
    function ResetPropertyLayer() {
    	
    	if (GetPropertyLayer() == null) {
    	
    		//shapeLayer = new VEShapeLayer();
    		//shapeLayer.SetClusteringConfiguration(VEClusteringType.Grid);
    		//SetPropertyLayer(shapeLayer); //new VEShapeLayer());
    		
    		SetPropertyLayer(new VEShapeLayer());
    		
            mVEMap.AddShapeLayer(GetPropertyLayer());
        } else {
            GetPropertyLayer().DeleteAllShapes();
        }
        return GetPropertyLayer();
    }
    this.ResetPropertyLayer = ResetPropertyLayer;
//    function ResetSearchLayer() {
//        if (RPSearchLayer == null) {
//            RPSearchLayer = new VEShapeLayer();
//            mVEMap.AddShapeLayer(RPSearchLayer);
//        } else {
//            RPSearchLayer.DeleteAllShapes();
//        }
//    }
//    this.ResetSearchLayer = ResetSearchLayer;
    function GetSiteDictionary() {
        return GetSiteContext().pindictionary;
    }
    this.GetSiteDictionary = GetSiteDictionary;    
    function SetSiteDictionary(val) {
        return GetSiteContext().pindictionary = val;
    }
    function GetKeyFromShapeIndex(shape, index) {
        return $(shape.Notes).find("input:checkbox").val();
    }
    function MakeIcon(cssclass, text) {
        return "<div class='" + cssclass + "'><span class='pinText'> " + text + " </span></div>";
    }
    this.MakeIcon = MakeIcon;
    function ShowPropertiesMapCallback(layer, resultsArray, places, hasMore, veErrorMessage) {
    	
        SetSiteDictionary({});
        var pindictionary = GetSiteDictionary();
        //infodictionary = {};
        if (layer != null) {
            var numShapes = layer.GetShapeCount();
            var defaultZoomForOnePin = 13;
            if (numShapes == 1) {
                mVEMap.SetZoomLevel(defaultZoomForOnePin);

                var point = layer.GetShapeByIndex(0).GetPoints()[0];
                if (point.Longitude == 0 && point.Latitude == 0) {
                    layer.DeleteAllShapes();
                    mVEMap.SetCenterAndZoom(new VELatLong(33, -110), 4);
                    return;
                }
            }
            numShapes = layer.GetShapeCount();
            for (var index = 0; index < numShapes; index++) {
                var shape = layer.GetShapeByIndex(index);
                //This part needs to be worked abit better :-P
                var key = GetKeyFromShapeIndex(shape, index);
                pindictionary[key] = shape; //
                //bless shape with key getting ability
                //capture key into a closure
                shape.RPGetKey = (function() {
                    var mykey = key;
                    return function() {
                        return mykey;
                    }
                })();
                //In case we're doing our own thing with the html..  (which in Camden, we do).
                if (!RPMOptions.useBingPopover) {
                    shape.RPTheRSSHtml = shape.Notes;
                    shape.Notes = "";
                    shape.Title = "";
                }
                var icon = MakeIcon("SmallPinStyleApartment", index + 1);
                shape.SetCustomIcon(icon);
            }
            //orient search or save place to go back to if needed.
            searchLocation = mVEMap.GetCenter();
        }
        if (layer == null) {
            alert(veErrorMessage);
        }
    }
    //public stuff
    this.ShowPropertiesMapCallback = ShowPropertiesMapCallback;
    this.FindProperties = function(strXMLURL, options) {
        if (strXMLURL == null) {
            alert("strXMLURL not passed; Map Cannot Load.");
            return;
        }
        ResetPropertyLayer()
        
        var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, strXMLURL, GetPropertyLayer());
        
        mVEMap.ImportShapeLayerData(veLayerSpec, this.ShowPropertiesMapCallback, true);
    }
    //More generic Callback maker
    function MapCallbackMaker(context) {
    	
    	function MapCallBack(layer, resultsArray, places, hasMore, veErrorMessage) {
    		
            context.pindictionary = {};
            context.IsPopulated = true;
            var numShapes = -1;
            if (layer != null) {
                numShapes = layer.GetShapeCount();
                for (var index = 0; index < numShapes; index++) {
                    var shape = layer.GetShapeByIndex(index);
                    if ($.isFunction(context.GetKeyFromShapeIndex)) {
                        var key = context.GetKeyFromShapeIndex(shape, index);
                        context.pindictionary[key] = shape; //
                        //bless shape with key getting ability
                        //capture key into a closure
                        shape.RPGetKey = (function() {
                            var mykey = key;
                            return function() {
                                return mykey;
                            }
                        })();
                    }
                    //In case we're doing our own thing with the html..  (which in Camden, we do).
                    if (!RPMOptions.useBingPopover) {
                    	
                        var prefix = "";
                        if (shape.Title != "")
                            prefix = "<strong class='title'>" + shape.Title + "</strong><br />"; 
                        shape.RPTheRSSHtml = prefix + shape.Notes;
                        shape.Notes = "";
                        shape.Title = "";
                    }
                    if ($.isFunction(context.MakeIconFromShapeIndex)) {
                        var icon = context.MakeIconFromShapeIndex(shape, index);
                        shape.SetCustomIcon(icon);
                    }
                }
            }
        }
        return MapCallBack;
    }
    this.MapCallbackMaker = MapCallbackMaker;
    this.FindByOptions = function(options) {
        mVEMap.Find(options.what, options.where, options.findType, options.shapeLayer, options.startIndex, options.numberOfResults, options.showResults, options.createResults, options.useDefaultDisambiguation, options.setBestMapView, options.callback);
    }
    this.CreateDefaultOptions = function(what,where,shapeLayer,numresults,callback){
        return {
            "what" : what,  //mustfill
            "where": where,  //mustfill
            "findType" : null,
            "shapeLayer": shapeLayer,
            "startIndex" : null,
            "numberOfResults": numresults,
            "showResults" : true,
            "createResults" : true,
            "useDefaultDisambiguation" : true,
            "setBestMapView" :true,
            "callback" :callback
            };
    }
    this.HideShapesByContext = function(contextName){
        var context = DictionaryOfContexts[contextName].layer.Hide();
    }
    this.ShowShapesByContext = function(contextName) {
        var context = DictionaryOfContexts[contextName].layer.Show();
    }
    this.FindByKeyword = function() { } //redefine elsewhere
    this.GetMap = function() {
        return mVEMap;
    }
    this.SetPOI = function(POI) {
        this.POI = POI;
    }
    this.GetPOI = function() {
        return this.POI;
    }
    this.GetSavedAddress = function(){
        return SavedAddress;
    }
    this.SetSavedAddress = function(_SavedAddress){
        SavedAddress = _SavedAddress;
    }
    this.AnimateResize = function(properties, options) {
        var newOptions = jQuery.extend({}, options, { complete: function() {
            if ("complete" in options) options.complete();
            var mwidth = $("#" + RPMOptions.id).width();
            var mheight = $("#" + RPMOptions.id).height();
            mVEMap.Resize(mwidth, mheight);
        }
        });
        $("#" + RPMOptions.id).animate(properties, newOptions);
    }
    this.GetDirections = function(options) {
    	if (typeof options == 'undefined' || options === null) {
    		options = {};
    	}
    	var decodedAddress = this.GetSavedAddress();
    	if (options.POI) {
    		this.SetPOI(options.POI);
    	}
    	//open the window now so that the window event is associated with the click event
    	//and thus not blocked by popup blockers.
    	this.MyPageFrame = window.open(AppRoot() + "map_blank.aspx", null, "menubar=no,location=no,toolbar=no,resizable=yes,scrollbars=1,status=no,width=710,height=850,left=100,top=10", null);

    	//window.focus();
    	
    	var opts = new VEGeocodeOptions();
    	opts.SetBestMapView = false;
    	opts.UseDefaultDisambiguation = false;

    	mVEMap.Geocode(decodedAddress, this.FindDirectionsGeocodeCallback_mVEMap_Geocode, opts);

    	//this.MyPageFrame = window.open("", null, "menubar=no,location=no,toolbar=no,resizable=yes,scrollbars=1,status=no,width=710,height=850,left=100,top=10", null);

    	//mVEMap.Find(null, decodedAddress, null, null, null, null, null, null, null, null,
    	//     this.FindDirectionsGeocodeCallback_mVEMap_Geocode);
    }
    
    this.MakeBingUrl = function(bestPlace) {
        //http://www.bing.com/community/site_blogs/b/maps/archive/2008/04/10/live-search-maps-api.aspx
        //http://www.bing.com/community/site_blogs/b/maps/archive/2006/02/25/map-control-zoom-levels-gt-resolution.aspx
        //905x705 or so  (not done yet)

        //this.MyPageFrame = window.open(AppRoot() + "map_blank.aspx" , "_blank", "menubar=no,location=no,toolbar=no,resizable=yes,scrollbars=1,status=no,width=710,height=850,left=100,top=10", null);
    
        var location = bestPlace.LatLong;
        var latA = location.Latitude;
        var longA = location.Longitude;
        var FromAddress = encodeURIComponent(thisRPMapObject.GetSavedAddress());
        var pointA = "rtp=pos." + latA + "_" + longA + "_" + FromAddress + "___e_~";


        var ToAddress = encodeURIComponent(thisRPMapObject.POI.GetAddress());
        var longB = thisRPMapObject.POI.GetLongitude();
        var latB = thisRPMapObject.POI.GetLatitude();
        var pointB = "pos." + latB + "_" + longB + "_" + ToAddress + "___e_";

        var centerpoint = "cp=" + ((Number(latA) + Number(latB)) / 2) + "," + ((Number(longA) + Number(longB)) / 2);
        var zoom = "z=11";
        var BingAddress = "http://www.bing.com/maps/print.aspx?mkt=en-us&" + zoom + "&s=r&";
        var pointKey = "&pt=pf&rs=v50%2C3jkUWQeiKEiqc43KE3n%2BVQ%3D%3D&";
        var options = "&mode=D&rtop=0~0~0~&cmw=1008&cmh=666&u=0";
        var Link = BingAddress + centerpoint + pointKey + pointA + pointB + options;
        return Link;
    }
    this.FindDirectionsGeocodeCallback_mVEMap_Geocode = function(shapelayer, findResults, places) {
    	if (places == null) {
    		thisRPMapObject.MyPageFrame.close();
    		alert('Address invalid');
    		return;
    	}

    	var bestPlace = places[0];
    	var Link = thisRPMapObject.MakeBingUrl(bestPlace);

    	//for now, just assume it'll take a few seconds to load the window.
    	//Ideally, we need to attach a "window ready event" from which we can fire this code
    	///but I can't do that at the moment.
    	// To load as quickly as possible, we attempt to load it in the window every so often
    	// untill there's no exception.  (we also try to keep the number of trys to a minimum).
    	var trycount = 0;
    	var interval = setInterval(function() {
    		if (trycount > 10) {
    			clearInterval(interval);
    			//alert('RP: cannot change new window url');
    			//thisRPMapObject.MyPageFrame.close();
    		}
    		trycount++;
    		try {
    			thisRPMapObject.MyPageFrame.focus();
    			thisRPMapObject.MyPageFrame.location = Link;
    			thisRPMapObject.MyPageFrame.focus();
    			clearInterval(interval);
    		} catch (e) { }
    	}, 250);
    }
    // for use with Map.Find
    this.FindDirectionsGeocodeCallback_mVEMap_Find = function(shapeLayer, findResults, places, moreResults, errorMsg) {
        thisRPMapObject.FindDirectionsGeocodeCallback_mVEMap_Geocode(shapeLayer, findResults, places);
    }

    //initialization stuff
    function constructor_helper() {
        if (!("id" in RPMOptions)) {
            warn("RPMap not given id for map");
        }
        if ("width" in RPMOptions) {
            $("#" + RPMOptions.id).css({ "width": parseFloat(RPMOptions.width) + "px" });
        }
        if ("height" in RPMOptions) {
            $("#" + RPMOptions.id).css({ "height": parseFloat(RPMOptions.height) + "px" });
        }
        if (RPMOptions.derivesize) {
            var mwidth = $("#" + RPMOptions.id).width();
            var mheight = $("#" + RPMOptions.id).height();
            $("#" + RPMOptions.id).css({ "width": parseFloat(mwidth) + "px" });
            $("#" + RPMOptions.id).css({ "height": parseFloat(mheight) + "px" });
        }
        if (!("useBingPopover" in RPMOptions)) {
            RPMOptions.useBingPopover = true;
        }
        if (mVEMap == null) {
            mVEMap = new VEMap(RPMOptions.id);
            if (RPMOptions.onLoadMap) {
                mVEMap.onLoadMap = RPMOptions.onLoadMap;
            }
            mVEMap.LoadMap();
            AddContext("Sites");
            
            mVEMap.AttachEvent("onclick", pinEventHandlerMaker('map_pin_click'));
            //mVEMap.AttachEvent("onclick", eventHandlerMaker('map_click'));
            mVEMap.AttachEvent("onclick", MouseShapeHandler);
            mVEMap.AttachEvent("onmouseover", pinEventHandlerMaker('map_pin_mouseover'));
            mVEMap.AttachEvent("onmouseout", pinEventHandlerMaker('map_pin_mouseout'));

        }
    }

    function MouseShapeHandler(e) {
    	if (e.elementID != null) {
    		var shape = mVEMap.GetShapeByID(e.elementID);
    		var strtitle = shape.GetTitle();
    		//alert('here' + strtitle);
    		
            var prop_Index_UseingAltitude;
            prop_Index_UseingAltitude = shape.GetAltitude();

            if (prop_Index_UseingAltitude != null) {
            	//alert('here ' + shape.GetTitle() + " " + prop_Index_UseingAltitude + " " + clust_ids_ar[prop_Index_UseingAltitude]);
            	//var point_ar = shape.GetPoints();


            	var clust_inner_shapeid = clust_ids_ar[prop_Index_UseingAltitude];

            	var inner_shapeid_ar = clust_inner_shapeid.split(',');

            	var point_ar = new Array();
            	var point_ar_index = 0;
            	
            	for (var i = 0; i < inner_shapeid_ar.length; ++i) {

            		if (inner_shapeid_ar[i].length > 0) {
            			var inner_shape = mVEMap.GetShapeByID(inner_shapeid_ar[i]);
            			if (inner_shape != null) {
            				var one_point = inner_shape.GetPoints();
            				point_ar[point_ar_index] = new VELatLong(one_point[0].Latitude, one_point[0].Longitude, 0);
            				//alert('here ' + " " + inner_shapeid_ar[i] + " " + one_point[0] + " " + point_ar[i]);
            				++point_ar_index;
            			}
            		}
            		
                }
                
            	//mVEMap.SetCenterAndZoom(point_ar[0], 15);

                //alert(" " + point_ar[0]);
                
            	mVEMap.SetMapView(point_ar);

            }
            
            /*
    		if (strtitle.indexOf('#') > 0) {
    			alert('here' + shape.GetTitle());
    			
    		}
    		*/
    		
        }
    }
    
    function eventHandlerMaker(jQueryEventTrigger) {
        return function(bingMapEvent) {
            var thingWasClicked = (bingMapEvent.elementID != null);
            $(document).trigger(jQueryEventTrigger, [thisRPMapObject, { thingClicked: thingWasClicked, bingMapEvent: bingMapEvent}]);
        }
    }
    function pinEventHandlerMaker(jQueryEventTrigger) {
        return function(bingMapEvent) {
            if (bingMapEvent.elementID != null) {
                var id;
                var shape = mVEMap.GetShapeByID(bingMapEvent.elementID);
                if (shape.RPGetKey) {
                    var key = shape.RPGetKey();
                    $(document).trigger(jQueryEventTrigger, [key, shape, thisRPMapObject, { thingClicked: true, bingMapEvent: bingMapEvent}]);
                }
            }
        }
    }

    //initialize
    constructor_helper();
    //pans the map to the shape with the specified key
    $(document).bind('list_item_click', function(e, key) {
        var VELatLong = GetSiteContext().pindictionary[key].GetPoints()[0];
        mVEMap.PanToLatLong(VELatLong)
    });
}

function RPPOI() {
    if (!(this instanceof RPPOI))
        return new RPPOI();
}
//GetAddress from Point Of Interest (to be defined later)
RPPOI.prototype.GetAddress = function() { return ""; } 
RPPOI.prototype.GetLongitude = function() { return 0; }
RPPOI.prototype.GetLatitude = function() { return 0; }


function RPMapScriptLoader() {
    if (!(this instanceof RPMapScriptLoader))
        return new RPMapScriptLoader();
}
RPMapScriptLoader.prototype.loading = false;  // use as a global.
RPMapScriptLoader.prototype.ShouldLoad = function() {
    return typeof VEMap == "undefined" && !RPMapScriptLoader.prototype.loading
}
RPMapScriptLoader.prototype.OnLoad = function (myClosure){
    $(document).bind("map_scripts_loaded",myClosure);
}
RPMapScriptLoader.prototype.IsLoaded = function(){
    return !(typeof VEMap == "undefined");
}
RPMapScriptLoader.prototype.Load = function() {
    function mapScriptFetched() {
        RPMapScriptLoader.prototype.loading = false;
        $(document).trigger("map_scripts_loaded");
    }
    function compatibilityNonsenseFetched() {
        $.getScript('http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3', mapScriptFetchedDelayed);
    }
    function mapScriptFetchedDelayed() {
        // this needed to cover a delay in getting the script and making it active which
        // will cause the pan button to be non-functional.
        setTimeout(mapScriptFetched, 200);
    }
    if (this.ShouldLoad()) {
        RPMapScriptLoader.prototype.loading = true;
        if ($.browser.mozilla) { $.getScript("http://ecn.dev.virtualearth.net/mapcontrol/v6.3/js/atlascompat.js", compatibilityNonsenseFetched); }
        else { $.getScript('http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2', mapScriptFetched); }
    } else if (this.IsLoaded) {
        mapScriptFetched();
    } else {
        //apparently we're invoking Load while it's actually loading.  Please Wait.
    }
    
}
