/**
 * @file Infoboxes support for Bing Maps AJAX Control 7.0
 * @see http://msdn.microsoft.com/en-us/library/gg427610.aspx
 * Requires jQuery 1.4.2+
 */

/*********************************************************************************************/

$('head').append('<style>.VE_Pushpin_Popup{position: absolute; z-index: 1000; display: none;}</style>');

 //Pushpin
Microsoft.Maps.Map.prototype.AddPushpin = function (location, options) {
    options._infobox = $('<div class="VE_Pushpin_Popup"></div>');

    var pin = new Microsoft.Maps.Pushpin(location, options);
    this.entities._tryLocationToPixel = this.tryLocationToPixel;
  
    var root = $(this.getRootElement());
    root.append(pin._infobox);

    this._entityAdded({ entity: pin, collection: this.entities }); // TODELETE: simulates the "entityAdded" event
   
    return pin;
    
}

//Polyline
Microsoft.Maps.Map.prototype.AddPolyline = function(locationsLine, optionsLine){
        optionsLine._infobox = $('<div class="VE_Pushpin_Popup"></div>');
        
       var polyline = new Microsoft.Maps.Polyline(locationsLine, optionsLine);

       this.entities._tryLocationToPixel = this.tryLocationToPixel;
    
        var root = $( this.getRootElement() );
        root.append(polyline._infobox);

     this._entityAdded({entity: polyline, collection: this.entities}); 

     return polyline;

}

//Polygon
Microsoft.Maps.Map.prototype.AddPolygon = function(locationsArea, optionsArea){
        optionsArea._infobox = $('<div class="VE_Pushpin_Popup"></div>');
        
       var polygon = new Microsoft.Maps.Polygon(locationsArea, optionsArea);

       this.entities._tryLocationToPixel = this.tryLocationToPixel;
    
        var root = $( this.getRootElement() );
        root.append(polygon._infobox);

     this._entityAdded({entity: polygon, collection: this.entities}); 

     return polygon;

}
   

/*********************************************************************************************/
//Pushpin
Microsoft.Maps.Pushpin.prototype.ToggleInfoBox = function(){
        if (this._infoboxShown) this.HideInfoBox();
        else this.ShowInfoBox();
};

//Polyline
Microsoft.Maps.Polyline.prototype.ToggleInfoBox = function(){
        if (this._infoboxShown) this.HideInfoBox();
        else this.ShowInfoBox();
};

//Polygon
Microsoft.Maps.Polygon.prototype.ToggleInfoBox = function(){
        if (this._infoboxShown) this.HideInfoBox();
        else this.ShowInfoBox();
};

//**************************************************************************************************
//Pushpin
Microsoft.Maps.Pushpin.prototype.ShowInfoBox = function(){
        var pos = this.tryLocationToPixel(
                this._location,
                Microsoft.Maps.PixelReference.control
        );
		
        this._infobox
         .css('left', pos.x  + 'px')
         .css('top', (pos.y - 70) + 'px')
         .show();
        this._infoboxShown = true;
};
Microsoft.Maps.Pushpin.prototype.HideInfoBox = function(){ 
       this._infobox.delay(2000).slideUp(100); //short transition
	this._infoboxShown = false;
};
  

////Polyline
Microsoft.Maps.Polyline.prototype.ShowInfoBox = function (locs) {
    var pos = this.tryLocationToPixel(locs, Microsoft.Maps.PixelReference.control);
     this._infobox 
         .css('left', pos.x + 'px')
         .css('top', pos.y + 'px')
         .show();
    this._infoboxShown = true;

};
Microsoft.Maps.Polyline.prototype.HideInfoBox = function(){ 
          this._infobox.delay(2000).slideUp(100); //short transition
	this._infoboxShown = false;
};


////Polygon
Microsoft.Maps.Polygon.prototype.ShowInfoBox = function (locsArea) {
    var pos = this.tryLocationToPixel(locsArea, Microsoft.Maps.PixelReference.control);
    this._infobox 
         .css('left', pos.x + 'px')
         .css('top', pos.y + 'px')
         .show();
    this._infoboxShown = true;

};
Microsoft.Maps.Polygon.prototype.HideInfoBox = function(){ 
       this._infobox.delay(2000).slideUp(100); //short transition
	this._infoboxShown = false;
};
  
/*********************************************************************************************/
//Pushpin
Microsoft.Maps.Pushpin.prototype._infoboxShown = false;
  
Microsoft.Maps.Pushpin.prototype._infoboxToggle = function(e){
      
        e.target.ToggleInfoBox();
};  

Microsoft.Maps.Pushpin.prototype._infoboxShow = function(e){
        var pinLoc = e.target.getLocation();
		e.target.ShowInfoBox();

    };

    Microsoft.Maps.Pushpin.prototype._infoboxHide = function (e) {
      
        e.target.HideInfoBox();
    };

  
 //Polyline 
Microsoft.Maps.Polyline.prototype._infoboxShown = false;

Microsoft.Maps.Polyline.prototype._infoboxToggle = function(e){
        e.target.ToggleInfoBox();
};



Microsoft.Maps.Polyline.prototype._infoboxShow = function (e) {

    var pointlist = new Array();
    pointlist = e.target.getLocations();
    var index4ancor = Math.round(pointlist.length/2);  
    var ancorpoint = pointlist[index4ancor];
    e.target.ShowInfoBox(ancorpoint);

};  
  
Microsoft.Maps.Polyline.prototype._infoboxHide = function(e){
      e.target.HideInfoBox();  
};


//Polygon
Microsoft.Maps.Polygon.prototype._infoboxShown = false;

Microsoft.Maps.Polygon.prototype._infoboxToggle = function(e){

        e.target.ToggleInfoBox();
};


Microsoft.Maps.Polygon.prototype._infoboxShow = function (e) {
    var loclist = new Array();
	loclist = e.target.getLocations();
    var index4ancor = Math.round(loclist.length/2);  
    var ancorpoint1 = loclist[index4ancor];
    e.target.ShowInfoBox(ancorpoint1);

};  
  
Microsoft.Maps.Polygon.prototype._infoboxHide = function(e){

        e.target.HideInfoBox();  
};


/*********************************************************************************************/
  
/** 
 * Called when an entity is added to the map.
 */

Microsoft.Maps.Map.prototype._entityAdded = function (e) {
    var entity = e.entity;
    var entity = e.entity;
    if (entity._infobox) {
        entity.tryLocationToPixel = e.collection._tryLocationToPixel;
        if (entity.sticky) {
            Microsoft.Maps.Events.addHandler(entity, 'click', entity._infoboxToggle);
            //  Microsoft.Maps.Events.addHandler(entity, 'touch', entity._infoboxToggle);
        }
        else {
            Microsoft.Maps.Events.addHandler(entity, 'mouseover', entity._infoboxShow);
            Microsoft.Maps.Events.addHandler(entity, 'mouseout', entity._infoboxHide);
        }
    }

};

/**  
 * Called when an entity is removed from the map.
 */

Microsoft.Maps.Map.prototype._entityRemoved = function(e){
        var entity = e.target;
        if (entity._infobox){
                entity.tryLocationToPixel = null;
                if (entity.sticky){
                       Microsoft.Maps.Events.removeHandler(entity, 'click', this._infoboxToggle);
                      // Microsoft.Maps.Events.removeHandler(entity, 'touch', this._infoboxToggle);
						
                } else {
                        Microsoft.Maps.Events.removeHandler(entity, 'mouseover', this._infoboxShow);
                        Microsoft.Maps.Events.removeHandler(entity, 'mouseout', this._infoboxHide);
                  
                }
                entity._infobox.remove();
        }
};


/*********************************************************************************************/
  
/**
 * Generates contents of the infobox and copy the extended options to the Pushpin instance (also called by the constructor).
 * NPO: if some options are missing, should it overwrite as NULL or leave the value as-is ? For now, it overwrites.
 */
//Pushpin
Microsoft.Maps.Pushpin.prototype._setOptions = Microsoft.Maps.Pushpin.prototype.setOptions;
Microsoft.Maps.Pushpin.prototype.setOptions = function(options){
        // Pushpin options
        this._setOptions(options);

        // Infobox options: overwrites as NULL properties that are not provided
        if (options.icon) this.icon = options.icon;
        if (options.anchor) this.anchor = options.anchor;
        if (options.sticky) this.sticky = options.sticky;
        if (options.title) this.title = options.title;
        if (options.description) this.description = options.description;
        if (options._infobox) this._infobox = options._infobox;

        // Infobox contents
        if (!options.infobox){  
                options.infobox = $('<div class="Title">' + this.title + '</div><div class="Description">' + this.description + '</div>');
        } else if (options.infobox && this.infobox && (options.infobox != this.infobox)){
                this._infobox.remove( this.infobox );
        }

        // Add-replace the contents inside the infobox wrapper of this specific pin
       this.infobox = options.infobox;
       this._infobox.append(this.infobox);

}; 

//Polyline  
Microsoft.Maps.Polyline.prototype._setOptions = Microsoft.Maps.Polyline.prototype.setOptions;
Microsoft.Maps.Polyline.prototype.setOptions = function(optionsLine){
      
        this._setOptions(optionsLine);

        // Infobox options: overwrites as NULL properties that are not provided
  
		if (optionsLine.strokeColor) this.strokeColor = optionsLine.strokeColor;
		if (optionsLine.strokeThickness) this.strokeThickness = optionsLine.strokeThickness;
        if (optionsLine.sticky) this.sticky = optionsLine.sticky;
        if (optionsLine.title) this.title = optionsLine.title;
        if (optionsLine.description) this.description = optionsLine.description;
        if (optionsLine._infobox) this._infobox = optionsLine._infobox;

        // Infobox contents
        if (!optionsLine.infobox){
                optionsLine.infobox = $('<div class="Title">' + this.title + '</div><div class="Description">' + this.description + '</div>');
        } else if (optionsLine.infobox && this.infobox && (optionsLine.infobox != this.infobox)){
                this._infobox.remove( this.infobox );
        }

        // Add-replace the contents inside the infobox wrapper of this specific pin
        this.infobox = optionsLine.infobox;
        this._infobox.append( this.infobox );
};


////Polygon
Microsoft.Maps.Polygon.prototype._setOptions = Microsoft.Maps.Polygon.prototype.setOptions;
Microsoft.Maps.Polygon.prototype.setOptions = function(optionsArea){
      
        this._setOptions(optionsArea);
   
        // Infobox options: overwrites as NULL properties that are not provided
        if (optionsArea.fillColor) this.fillColor = optionsArea.fillColor;
        if (optionsArea.strokeColor) this.strokeColor = optionsArea.strokeColor;
		if (optionsArea.strokeThickness) this.strokeThickness = optionsArea.strokeThickness;
        if (optionsArea.sticky) this.sticky = optionsArea.sticky;
        if (optionsArea.title) this.title = optionsArea.title;
        if (optionsArea.description) this.description = optionsArea.description;
        if (optionsArea._infobox) this._infobox = optionsArea._infobox;
		
        // Infobox contents
        if (!optionsArea.infobox){
                optionsArea.infobox = $('<div class="Title">' + this.title + '</div><div class="Description">' + this.description + '</div>');
        } else if (optionsArea.infobox && this.infobox && (optionsArea.infobox != this.infobox)){
                this._infobox.remove( this.infobox );
        }

        // Add-replace the contents inside the infobox wrapper of this specific pin
        this.infobox = optionsArea.infobox;
        this._infobox.append( this.infobox );
};


/*********************************************************************************************/

/**
 * Moving the map should close any infobox that is open, even sticky ones (that way the transition is faster)
 */
Microsoft.Maps.Map.prototype._viewstart = function(){
        var viewreopen = this.target._viewreopen;
        var entities = this.target.entities;
        var l = entities.getLength();
        for (var i = 0; i < l; i++){
                var entity = entities.get(i);
                if (entity._infoboxShown){
                        entity.HideInfoBox();
                        //if (entity.sticky) viewreopen.push(entity);
                }
        }
}


Microsoft.Maps.Map.prototype._closeInfoboxbyViewChange = function(){
  try {      
        var entities = this.target.entities;
	    var l = entities.getLength();
		for (var i = 0; i < l; i++){
                var collecInEntity = entities.get(i);
				for (var i1 = 0; i1 < collecInEntity.getLength(); i1++){
				var ding = collecInEntity.get(i1);
				if (ding._infoboxShown){
				 ding.HideInfoBox();
                }
				}
				
         }

        } catch (e) {
            var viewreopen = this.target._viewreopen;
            var entities = this.target.entities;
            var l = entities.getLength();
            for (var i = 0; i < l; i++) {
                var entity = entities.get(i);
                if (entity._infoboxShown) {
                    entity.HideInfoBox();
                    if (entity.sticky) viewreopen.push(entity);
                }
            }
        }
}
    


/**
 * Once the map stops moving, reopen sticky infoboxes that were open
 */
/*********************************************************************************************/

/** 
 * Extended "Map" constructor to listen to collection changes and map movements.
 */
Microsoft.Maps._Map = Microsoft.Maps.Map;
Microsoft.Maps.Map = function(container, options){
        var map = new Microsoft.Maps._Map(container, options);
        // Sticky infoboxes that were open when the map starts changing of view
        // and that should be re-open when the view change ends.
        map._viewreopen = new Microsoft.Maps.EntityCollection();

        // Entities collection events
        Microsoft.Maps.Events.addHandler(map.entities, 'entityAdded', map._entityAdded);
        Microsoft.Maps.Events.addHandler(map.entities, 'entityRemoved', map._entityRemoved);
        //Microsoft.Maps.Events.addHandler(map.entities, 'entityChanged', map._entityChanged);

        // Map movement (closes non-sticky infoboxes)
        Microsoft.Maps.Events.addHandler(map, 'viewchangestart', map._viewstart);
        Microsoft.Maps.Events.addHandler(map, 'viewchangeend', map._viewend);
       
       
        return map;
};

/*********************************************************************************************/


