 var MarkerLabels = {'1':'A','2':'B','3':'C','4':'D','5':'E','6':'F','7':'G','8':'H','9':'I','10':'J','11':'K','12':'L','13':'M','14':'N','15':'O','16':'P','17':'Q','18':'R','19':'S','20':'T','21':'U','22':'V','23':'W','24':'X','25':'Y','26':'Z'}
function DSPoiFlyoutContentFactory( p ) {
    this.poi = p;
}
DSPoiFlyoutContentFactory.createAmbigFlyout = function( poi ) {
    var d = DOMNode.create( null, '', 'div', 'class', 'flyout' );
    var name = poi.getProperty( 'name' );

    var a = DOMNode.create( d, name, 'a', 'href', 'javascript:void(0)', 'class', 'ambigEntry' );
    a.addEventListener( 'click', function() { poi.showFlyout() }, false );
    var i = 0;

    for( var it = new DSMapObject_Iterator( poi.collisions ); it.hasNext(); ) {
        var o = it.next();
        var _name = ( o.getProperty( 'name' ).length ? o.getProperty( 'name' ) : o.getProperty( 'businessName' ) );
        a = DOMNode.create( d, _name, 'a', 'href', 'javascript:void(0)', 'class', 'ambigEntry ambigSep' );
        a.addEventListener( 'click', DSPoi_FlyoutFactory( o ), false );
    }
    return [ 'Multiple Matches:', d ];
};
DSPoiFlyoutContentFactory.createBriefInfoFlyout = function( poi ) {
var title, a;
    var d = DOMNode.create( null, '', 'div', 'class', 'flyout' );

    var name = poi.getProperty( 'name' );

    if( name.length ) {

            title = DOMNode.create( d, name, 'a', 'href', 'javascript:void(0)', 'class', 'flyoutName' );
            title.addEventListener( 'click', DSPoi_FlyoutFactory( poi ), false );
       
        a = DOMNode.create( d, 'Click for more information', 'p' );
    }
    return [ title, d ];
};
DSPoiFlyoutContentFactory.createLocInfoFlyout = function( poi ) {
    var title, a;
    var d = DOMNode.create( null, '', 'div', 'class', 'flyout' );

    var name = poi.getProperty( 'name' );

    if( name.length ) {
        if( poi.getProperty( 'profile' ) ) {
            // view details link
            title = DOMNode.create( null, name, 'a', 'href', poi.getProperty( 'profile' ), 'class', 'flyoutName','target','_blank' );
            //title.addEventListener( 'click', PostLink, false );
        } else {
            title = DOMNode.create( null, name, 'div', 'class', 'flyoutName' );
        }
    }

    if ( poi.getProperty( 'address' ) ) {
        a = DOMNode.create( d, poi.getProperty( 'address' ), 'p' );
    }

    var csz = '';
    if ( poi.getProperty( 'city' ) ) { csz += poi.getProperty( 'city' ); }
    if ( poi.getProperty( 'state') ) { csz += ( csz ? ', ' : '' ) + poi.getProperty( 'state' ); }
    if ( poi.getProperty( 'zip') ) { csz += ( csz ? ' ' : '' )  + poi.getProperty( 'zip' ); }
    if ( csz ) {
        a = DOMNode.create( d, csz, 'p' );
    }

    if ( poi.getProperty( 'phoneNumber' ) ) {
        a = DOMNode.create( d, poi.getProperty( 'phoneNumber' ), 'p', 'style', 'font-weight: bold' );
    }

    
        // website link
        var _url = poi.getProperty( 'url' );
        if ( _url && _url != 'null' ) {
            a = DOMNode.create( d, 'View Website', 'a', 'href', _url, 'target', '_blank' );
        }
    var dir = DOMNode.create(null, '', 'p', 'style', 'margin-top:10px' );
    dir.innerHTML = 'Get directions <a href="/maps.html?Action=directions&toname=' + escape(name) + '&tolatlng=' + escape(poi.point.lat + '|' + poi.point.lng) + '">to</a> or <a href="/maps.html?Action=directions&fromname=' + escape(name) + '&fromlatlng=' + escape(poi.point.lat + '|' + poi.point.lng) + '">from</a> this location';
    d.appendChild(dir);
    return [ title, d ];
};


DSPoiFlyoutContentFactory.types = {
    briefInfo: DSPoiFlyoutContentFactory.createBriefInfoFlyout,
    locInfo: DSPoiFlyoutContentFactory.createLocInfoFlyout,
    ambig: DSPoiFlyoutContentFactory.createAmbigFlyout
};
DSPoiFlyoutContentFactory.addType = function( type, func ) {
    DSPoiFlyoutContentFactory.types[type] = func;
};
DSPoiFlyoutContentFactory.prototype.getByType = function( type ) {
    if( typeof DSPoiFlyoutContentFactory.types[type] == 'function' ) {
        return DSPoiFlyoutContentFactory.types[type]( this.poi, type );
    }
    return null;
};

function DSPoi_FlyoutFactory( o, type ) {
    return function() {
        o.showFlyout( type );
    }
}

function Poi(lat, lng, marker)
{ 
    this.init(lat, lng, marker );
}
Poi.prototype = new DSMapObject();
Poi.superclass = DSMapObject.prototype;
Poi.collection = new DSMapObject_Collection();
Poi.prototype.init = function( lat, lng, marker) 
{
    this.width = 20;
    this.height = 27
	this.flyouts = {};
    this.collisions = new DSMapObject_Collection();
	var latlong = new DSPoint(lat,lng);
	var newelm = DSMap.createElement(null,'div');
    var imgelm = DSMap.createImage(marker,newelm,null,null,null,24,29);
   
    this.flyoutContentFactory = new DSPoiFlyoutContentFactory( this );
    this.flyoutCreator = DSFlyout;
	if ( arguments.length ) {
		Poi.superclass.init.call(this, latlong, newelm, 24, 29);
	}
    DOMNode.editStyleValue( this.element, 'cursor', 'pointer' );
	this.addEventListener("mouseover",this.mouseover);
	this.addEventListener("click",this.click);
    this.dspoiId = Poi.collection.add( this );    
};
function Poi_ScrollMapToFlyout( f ) {
    var x = 0;
    var y = 0;
    var m = map.mapLayer;
    var vp = map.viewport;
    var left = parseInt( f.element.style.left ) + parseInt( m.style.left );
    var xBuffer = 15;
    var yBuffer = 15;
    if( left + f.element.offsetWidth + xBuffer > vp.offsetWidth ) {
        x = f.element.offsetWidth - vp.offsetWidth + left + xBuffer;
    }
    var top = parseInt( f.element.style.top ) + parseInt( m.style.top );
    if( top + f.element.offsetHeight + yBuffer > vp.offsetHeight ) {
        y = f.element.offsetHeight - vp.offsetHeight + top + yBuffer;
    }
    if( x != 0 || y != 0 )  {
        map.slideBy( -x, -y );
    }
}
Poi.prototype.setFlyoutCreator = function( f ) {
    this.flyoutCreator = f;
};
Poi.prototype.createFlyout = function( flyoutType ) {
    var a, o;

    var content = this.flyoutContentFactory.getByType( flyoutType );
    if( content ) {
        this.flyouts[flyoutType] = { type: flyoutType, id: null, flyout: new this.flyoutCreator( this.point, content[0], content[1] ) };
    }
    if( flyoutType == 'locInfo' ) {
        // TODO: what is this for, is there a better way to do it?
        DOMNode.addClass( this.flyouts[flyoutType].flyout.element, 'flyoutTop' );
    }

    return this.flyouts[flyoutType];
};
Poi.prototype.getFlyoutByType = function( type ) {
    return this.flyouts[type];
};
Poi.prototype.getActiveFlyout = function() {
    for( var i in this.flyouts ) {
        var f = this.flyouts[i];
        if( typeof f == 'object' && f.id ) {
            return f;
        }
    }
    return null;
};
Poi.prototype.hideFlyout = function() {
    for( var i in this.flyouts ) {
        var f = this.flyouts[i];
        if( typeof f == 'object' && f.id ) {
            map.removeObject( this.flyouts[i].id );
            this.flyouts[i].id = null;
        }
    }
};
Poi.prototype.needNewFlyout = function() {
    return false;
};
Poi.prototype.showFlyout = function( type, scroll ) {
    var f;
    if( ! type ) {
        type = this.getProperty( 'defaultFlyout' ) || 'locInfo';
    }
    if(!scroll) scroll = false;
    Poi.HideFlyouts();
    if ( this.needNewFlyout() || !( f = this.getFlyoutByType( type ) ) ) {
        f = this.createFlyout( type );
    }
    if( f ) {
        f.id = map.addObject( f.flyout );
        /* TODO: this scrollMap should, maybe, be put in the map class */
        if(scroll)this.scrollMapToFlyout( f.flyout );
    }
};

Poi.prototype.hoverFlyout = function( e ) {
    // sometimes the mouseout event doesn't fire when opening a flyout
   
    this.findCollisions();
    var currState, type;
    var f = this.getActiveFlyout();
    if( f ) {
        //Poi.HideFlyouts();
    } else  if ( this.collisions.size() ) {
        this.showFlyout( 'ambig' );
    } else {
        var fType = 'briefInfo';
        this.showFlyout( fType );
    }
    e.stopPropagation(); // don't let the mapClick event close us
};

Poi.prototype.clickFlyout = function( e ) {
    // sometimes the mouseout event doesn't fire when opening a flyout
   
    this.findCollisions();
    var currState, type;
    var f = this.getActiveFlyout();
    if(f && f.type == "briefInfo")
    {
        this.hideFlyout();
        f = null;
    }
    if( f ) {
        this.scrollMapToFlyout( f.flyout );
    } else  if ( this.collisions.size() ) {
        this.showFlyout( 'ambig' );
    } else {
        var fType = 'locInfo';
        this.showFlyout( fType,true );
    }
    e.stopPropagation(); // don't let the mapClick event close us
};

Poi.HideFlyouts = function() {
    for( var it = new DSMapObject_Iterator( Poi.collection ); it.hasNext(); it.next().hideFlyout() );
};
Poi.prototype.mouseover = function (e,o)
{
    o.hoverFlyout( e );
}
Poi.prototype.click = function (e,o)
{
    o.clickFlyout( e );
}
Poi.prototype.scrollMapToFlyout = Poi_ScrollMapToFlyout;       
Poi.prototype.findCollisions = function() {
    this.collisions.removeAll();
    for( var it = new DSMapObject_Iterator( Poi.collection ); it.hasNext(); ) {
        o = it.next();

        if( o !== this && _util_overlaps( this, o, (o.width/3), (o.height/3) ) ) {
            this.collisions.add( o );
        }
    }
};
  
/*
 * Utility functions
 */
function _util_overlaps( o1, o2, hTolerance, vTolerance ) {
    if ( !hTolerance ) { hTolerance = 0; }
    if ( !vTolerance ) { vTolerance = 0; }
    /*
    * bounding box checks... if the distance of the centers is < sum
    * of the extents, they they overlap
    */
    var e1 = o1.element;
    var e2 = o2.element;

    // extents
    var ve1 = o1.height / 2;
    var ve2 = o2.height / 2;
    var he1 = o1.width / 2;
    var he2 = o2.width / 2;

    // i want the centers so get left + horiz extent, etc
    var x1 = parseInt( e1.style.left ) + he1;
    var y1 = parseInt( e1.style.top ) + ve1;
    var x2 = parseInt( e2.style.left ) + he2;
    var y2 = parseInt( e2.style.top ) + ve2;

    var hOverlap = ( he1 + he2 ) - Math.abs( x2 - x1 );
    var vOverlap = ( ve1 + ve2 ) - Math.abs( y2 - y1 );
    return( hOverlap > hTolerance && vOverlap > vTolerance );
}
  //-->