LMI.MapExamples = (function() {
    var M = LMI.Mapping, // shortcut to Mapping package
        E = LMI.Element; // shortcut to LMI.Element package

        M.Tile.config = {
            defaultTile: 'images/pixel_trans.gif',
            brokenTile: 'images/map_unavailable.gif'
        };
        if( 'OverlayTile' in M ) {
            M.OverlayTile.config = {
                brokenTile: 'images/pixel_trans.gif'
            };
        }
        M.TileUrl.config = {
            baseUrl: 'http://kartat.02.fi/tiles/maps/',
            locale: 'en_DK',
            suffix: '&c=dgs-allbiz-dev'
        };
        M.TileManager.config = {
            tileLevels: [ 5,6,8,10,11,13,14,15,16,17,18,19,20 ],
            totalLevels: 13,
            minLevel: 3,
            maxLevel: 13,
            copyright: 'Kartat 2008 NLS Finland, Tele Atlas'
        };
        if( 'AerialTileManager' in M ) {
            M.AerialTileManager.config = {
                tileUrlOptions: {
                    baseUrl: 'http://kartat.02.fi/tiles/aerial/',
                    extension: '.jpeg'
                },
                minLevel: 1,
                copyright: 'Ilmakuvat 2008  NLS Finland, aeroGRID, Blom, DigitalGlobe'
            };
        }
        if( 'HybridTileManager' in M ) {
            M.HybridTileManager.config = {
                tileUrlOptions: {
                    baseUrl: 'http://kartat.02.fi/tiles/aerial/',
                    extension: '.jpeg'
                },
                overlayUrlOptions: {
                    baseUrl: 'http://kartat.02.fi/tiles/hybrids/'
                },
                copyright: '2008  NLS Finland, Tele Atlas, aeroGRID, Blom, DigitalGlobe'
            };
        }
        if( 'TopoTileManager' in M ) {
            M.TopoTileManager.config = {
                tileUrlOptions: {
                    baseUrl: 'http://kartat.02.fi/tiles/topographic/',
                    fallBackUrl: 'http://kartat.02.fi/tiles/maps/',
                    minTopoLevel: 14,
                    maxTopoLevel: 16
                },
                copyright: 'Kartat 2008  NLS Finland',
                tileUrlStrategy: LMI.Mapping.TopoTileUrl
            };
        }

    /**
     * @method isAncestor
     * @param {HTMLElement} el
     * @param {HTMLElement} ancestor
     * @return {Boolean}
     * @private
     */
    function isAncestor( el, ancestor ) {
        while( el ) {
            if( el === ancestor ) {
                return true;
            }
            el = el.parentNode;
        }
        return false;
    }

    return {
        /**
         * map options
         * @member options
         */
        options: {
            defaultLat: 61.4980,
            defaultLng: 23.7647,
            emptyZoom: 9,
            imageBase: 'images/',
            pixelUrl: 'images/pixel_trans.gif',
            enableResize:false,
            enableOverview: true,
            mapImageUrl: 'http://kartat.02.fi/tiles/maps/?uid=examples-mapping-dev'
        },
        /**
         * example locations
         * @member locations
         */
        locations: [
            { name: 'point 1', address: '123 Main St.', city: 'Anytown', postalCode: '33100', lat: 61.53014, lng: 23.63031 },
            { name: 'point 2', address: '143 Main St.', city: 'Anytown', postalCode: '33120', lat: 61.48411, lng: 23.76241 },
            { name: 'point 3', address: '163 Main St.', city: 'Anytown', postalCode: '33140', lat: 61.50005, lng: 23.75166 }
        ],
        /**
         * add plain icons to the map
         * @member addLocationsToMap
         * @param {LMI.Mapping.Map} map     the map to which icons should be added
         * @param {Array} locs              array of locations to add
         */
         addLocationsToMap: function( map, locs ) {
            for( var i = 0; i < locs.length; ++i ) {
                map.addObject( new M.SimpleMapObject( locs[i].lat, locs[i].lng ) );
            }

        },
        /**
         * add lettered icons to the map
         * @member addLetteredLocationsToMap
         * @param {LMI.Mapping.Map} map     the map to which icons should be added
         * @param {Array} locs              array of locations to add
         */
        addLetteredLocationsToMap: function( map, locs ) {
            for( var i = 0; i < locs.length; ++i ) {
                map.addObject( new M.Icon( new M.Point( locs[i].lat, locs[i].lng ), i ) );
           }
        },
        /**
         * update #centerPoint with the new center point of the map
         * @member displayMapCenter
         * @param {Object} e    custom event object
         */
        displayMapCenter: function( e ) {
            var p = document.getElementById( 'centerPoint' );
            p.innerHTML = e.center.lat + ',' + e.center.lng;
        },
        /**
         * alerts the name of the location that was clicked on
         * @member showLocationName
         * @param {Object} e                custom event object
         * @param {LMI.Mapping.Object} o    the icon that was clicked
         */
        showLocationName: function( e, o ) {
            alert( o.getProperty( 'name' ) );
        },
        /**
         * adds locations to the map and adds a click listener to each one
         * @method addLocsToMapWithClick
         * @param {LMI.Mapping.Map} map     the map to which icons should be added
         * @param {Array} locs              array of locations to add
         */
        addLocsToMapWithClick: function( map, locs ) {
            for( var i = 0; i < locs.length; ++i ) {
                var l = locs[i];
                var icon =  new M.Icon( new M.Point( l.lat, l.lng ), i );
                icon.setProperty( 'name', l.name );
                icon.addEventListener( 'click', LMI.MapExamples.showLocationName );
                map.addObject( icon );
             }
        },
        /**
         * creates the content to be displayed in a flyout
         * @member flyoutContentCreator
         * @param {LMI.Mapping.IconWithFlyout}  poi
         * @return {HTMLElement}
         */
        flyoutContentCreator: function( poi ) {
            return E.create( 'div', null, { children: [
                { tag: 'p', text: poi.getProperty( 'name' ) },
                { tag: 'p', text: poi.getProperty( 'address' ) },
                { tag: 'p', text: poi.getProperty( 'postalCode' ) + ', ' + poi.getProperty( 'city' ) }
            ] } );
        },
        /**
         * adds icons with flyouts to the map
         * @member addLocsWithFlyoutsToMap
         * @param {LMI.Mapping.Map} map     the map to which icons should be added
         * @param {Array} locs              array of locations to add
         */
        addLocsWithFlyoutsToMap: function( map, locs ) {
            // used this way all instances of IconWithFlyout
            // will share this content creator
            M.IconWithFlyout.flyoutFactory.addContentCreator( 'default', LMI.MapExamples.flyoutContentCreator );

            for( var i = 0; i < locs.length; ++i ) {
                var l = locs[i];
                var icon =  new M.IconWithFlyout( new M.Point( l.lat, l.lng ), i );
                icon.setProperties( 'name', l.name, 'address', l.address, 'city', l.city, 'postalCode', l.postalCode );
                map.addObject( icon );
             }
        },
        /**
         * creates the content to be displayed in a tip
         * @member tipContentCreator
         * @param {LMI.Mapping.IconWithFlyout}  poi
         * @return {HTMLElement}
         */
        tipContentCreator: function( poi ) {
            return E.create( 'div', null, { text: poi.getProperty( 'name' ) } );
        },
        /**
         * @member tipStyleCreator
         * @param {HTMLElement} content         the content that will be wrapped in this style
         * @param {LMI.Mapping.MapObject} poi   the poi
         */
        tipStyleCreator: function( content, poi ) {
            var tip = E.create( 'div', null, { style: 'background-color: #fff;border:1px solid #ccc' } );
            tip.appendChild( content );
            return tip;
        },
        /**
         * adds icons with flyouts, and mouseovers to the map
         * @member addLocsWithFlyoutsAndTipsToMap
         * @param {LMI.Mapping.Map} map     the map to which icons should be added
         * @param {Array} locs              array of locations to add
         */
        addLocsWithFlyoutsAndTipsToMap: function( map, locs ) {
            // used this way all instances of IconWithFlyout
            // will share this content creator
            M.IconWithFlyout.flyoutFactory.addContentCreator( 'default', LMI.MapExamples.flyoutContentCreator );
            M.IconWithFlyout.flyoutFactory.addContentCreator( 'tip', LMI.MapExamples.tipContentCreator );
            M.IconWithFlyout.flyoutFactory.addStyle( 'tip', LMI.MapExamples.tipStyleCreator, { xOffset: 5, yOffset: 27 } );

            for( var i = 0; i < locs.length; ++i ) {
                var l = locs[i];
                var icon =  new M.IconWithFlyout( new M.Point( l.lat, l.lng ), i );
                icon.setProperties( 'name', l.name, 'address', l.address, 'city', l.city, 'postalCode', l.postalCode );
                icon.addEventListener( 'mouseover', function( e, o ) {
                    var f = o.getActiveFlyout( o );
                    if( ! f ) {
                        // first parameter is the content, second is the style
                        o.showFlyout( 'tip', 'tip' );
                    }
                } );
                icon.addEventListener( 'mouseout', function( e, o ) {
                    var f = o.getActiveFlyout( o );
                    if( f && f.type === 'tip' ) {
                        o.hideFlyout();
                    }
                } );
                map.addObject( icon );
             }
        }

    };
})();

