﻿
var _exploreMap = null;

var ExploreMap = Class.create();
var Development = Class.create();

Development.prototype = {
    ///<summary>Development object for use with google maps</summary>
    
    Title : null,
        
    HasSpecialOffer : false,
        
    BedroomCount : null,
    
    PriceFrom : null,
    
    ImageUrl : null,
    
    Latitude : null,
    
    Longitude : null,
    
    StreetAddress : null,
    
    City : null,
    
    Postcode : null,
    
    DevelopmentUrl : null,

    IsCurrent: null,

    IsProcessed: false,

    Locality: null,
    
    initialize: function() {
    }
};

ExploreMap.prototype = {
    ///<summary>
    //</summary>

    // ID of the map element
    mapElementID: null,

    // two dimentional array of developments inc. lat\lng cords
    developmentPoints: null,

    // internal map reference
    map: null,

    // geo-coder object
    geoCoder: null,

    // map bounds
    bounds: null,

    // default center lat (Edinburgh-ish)
    centerLat: 55.9584,

    // default center lng (Edinburgh-ish)
    centerLng: -3.19702,

    // default zoom level
    zoom: 13,

    // geo-coder retry delay
    delay: 100,

    // enable map dragging 
    enableDrag: true,

    // enable map info window
    enableInfoWindow: true,

    // enable double click zooming
    enableDoubleClickZoom: true,

    // enable scroll wheel zooming
    enableScrollWheelZoom: true,

    // default icon
    icon: null,

    // current development icon    
    currentIcon: null,

    // current development alt icon
    currentAltIcon: null,

    // current development icon graphic
    currentIconImage: '/Miller.HomesWeb/img/GIcons/current_icon1.png',
    currentIconImage_IE: '/Miller.HomesWeb/img/GIcons/current_icon1.gif',

    // current icon shadow
    currentIconImageShadow: '/Miller.HomesWeb/img/GIcons/shadow1.png',

    // current development icon rollover graphic
    currentIconAltImage: '/Miller.HomesWeb/img/GIcons/current_iconAlt1.png',
    currentIconAltImage_IE: '/Miller.HomesWeb/img/GIcons/current_iconAlt1.gif',

    // current icon shadow
    currentIconAltImageShadow: '/Miller.HomesWeb/img/GIcons/shadow2.png',

    // future development icon    
    futureIcon: null,

    // future development alt icon    
    futureAltIcon: null,

    // future development icon graphic
    futureIconImage: '/Miller.HomesWeb/img/GIcons/future_icon1.png',
    futureIconImage_IE: '/Miller.HomesWeb/img/GIcons/future_icon1.gif',

    // future icon shadow
    futureIconImageShadow: '/Miller.HomesWeb/img/GIcons/shadow1.png',

    // future development icon rollover graphic
    futureIconAltImage: '/Miller.HomesWeb/img/GIcons/future_iconAlt1.png',
    futureIconAltImage_IE: '/Miller.HomesWeb/img/GIcons/future_iconAlt1.gif',

    // future icon shadow
    futureIconAltImageShadow: '/Miller.HomesWeb/img/GIcons/shadow2.png',

    iconCollection: null,

    // number of points plotted
    plottedCount: 0,
    plottedAttempts: 0,
    plotAddressFailures: 0,

    initialize: function(elMap, defLat, defLng) {
        ///<summary>Object initialiser</summary>

        this.mapElementID = elMap;
        this.centerLat = defLat;
        this.centerLng = defLng;
        this._initIcons();
        this.iconCollection = new Array();
        this.geoCoder = new GClientGeocoder();

        _exploreMap = this;

        // init map
        this.map = new GMap2(document.getElementById(this.mapElementID));
    },

    is_ie6: function() {
        return (navigator.userAgent.toLowerCase().indexOf('msie 6') != -1);
    },

    _initIcons: function() {
        ///<summary>Initialise icons</summary>
        ///<remarks>Internal method</remarks>

        var baseIcon = new GIcon();
        baseIcon.iconSize = new GSize(28, 28);
        if (this.is_ie6())
            baseIcon.shadowSize = null;
        else
            baseIcon.shadowSize = new GSize(36, 36);
        baseIcon.iconAnchor = new GPoint(12, 16);
        baseIcon.infoWindowAnchor = new GPoint(8, 4);

        var baseAltIcon = new GIcon();
        baseAltIcon.iconSize = new GSize(39, 39);
        if (this.is_ie6())
            baseAltIcon.shadowSize = null;
        else
            baseAltIcon.shadowSize = new GSize(46, 46);
        baseAltIcon.iconAnchor = new GPoint(16, 18);
        baseAltIcon.infoWindowAnchor = new GPoint(8, 4);

        // create the current icon based on the base icon properties
        this.currentIcon = new GIcon(baseIcon);
        if (this.is_ie6())
            this.currentIcon.image = this.currentIconImage_IE;
        else
            this.currentIcon.image = this.currentIconImage;
        if (this.is_ie6())
            this.currentIcon.shadow = null;
        else
            this.currentIcon.shadow = this.currentIconImageShadow;

        // and the Alt icon
        this.currentAltIcon = new GIcon(baseAltIcon);
        if (this.is_ie6())
            this.currentAltIcon.image = this.currentIconAltImage_IE;
        else
            this.currentAltIcon.image = this.currentIconAltImage;
        if (this.is_ie6())
            this.currentAltIcon.shadow = null;
        else
            this.currentAltIcon.shadow = this.currentIconAltImageShadow;

        // create the future icon based on the base icon properties
        this.futureIcon = new GIcon(baseIcon);

        if (this.is_ie6())
            this.futureIcon.image = this.futureIconImage_IE;
        else
            this.futureIcon.image = this.futureIconImage;
        if (this.is_ie6())
            this.futureIcon.shadow = null;
        else
            this.futureIcon.shadow = this.futureIconImageShadow;

        // and the Alt icon
        this.futureAltIcon = new GIcon(baseAltIcon);
        if (this.is_ie6())
            this.futureAltIcon.image = this.futureIconAltImage_IE;
        else
            this.futureAltIcon.image = this.futureIconAltImage;
        if (this.is_ie6())
            this.futureAltIcon.shadow = null;
        else
            this.futureAltIcon.shadow = this.futureIconAltImageShadow;
    },

    load: function(developments, defaultLat, defaultLng, defaultZoom) {
        ///<summary></summary>
        ///<param name="developments">Collection of developments in this area</param>
        ///<param name="defaultLat">default latitude used when there are no developments</param>
        ///<param name="defaultLng">default longitude used when there are no developments</param>
        ///<param name="defaultZoom">default zoom level used when there are no developments</param>

        this.developmentPoints = developments;

        if (!this.mapElementID)
            throw "Map element ID not specified";

        if (GBrowserIsCompatible()) {

            this.bounds = new GLatLngBounds();

            // pan\zoom control
            this.map.addControl(new GLargeMapControl());

            if (!this.enableDrag)
                this.map.disableDragging();

            if (!this.enableInfoWindow)
                this.map.disableInfoWindow()

            if (!this.enableDoubleClickZoom)
                this.map.enableDoubleClickZoom()

            if (this.enableScrollWheelZoom)
                this.map.enableScrollWheelZoom();

            if (!defaultLat)
                defaultLat = this.centerLat;

            if (!defaultLng)
                defaultLng = this.centerLng;

            if (!defaultZoom)
                defaultZoom = this.zoom;

            this.map.setCenter(new GLatLng(defaultLat, defaultLng), defaultZoom);

            $('elNoResults').style.display = 'none';

            //
            if (this.developmentPoints == null) {
                // no developments specified - default center\zoom
                this.map.setCenter(new GLatLng(defaultLat, defaultLng), defaultZoom);
                this.showNoResultPanel();

            } else {
                var maxLen = this.developmentPoints.length;

                $('elNoResults').style.display = 'none';

                if (maxLen > 0) {

                    var i = 0;
                    while (i < maxLen) {

                        if (this.developmentPoints[i].IsProcessed == false) {
                            var matchedArray = new Array();

                            // take the first development
                            this.developmentPoints[i].IsProcessed = true;

                            matchedArray.push(this.developmentPoints[i]);

                            // find any other with the same postcode
                            for (var j = 0; j < this.developmentPoints.length; j++) {
                                if (this.developmentPoints[j].IsProcessed == false) {

                                    var thisPostcode = this.developmentPoints[j].Postcode.toLowerCase();
                                    var matchPostcode = this.developmentPoints[i].Postcode.toLowerCase();

                                    var thisLat = this.developmentPoints[j].Latitude;
                                    var thisLng = this.developmentPoints[j].Longitude;

                                    var matchLat = this.developmentPoints[i].Latitude;
                                    var matchLng = this.developmentPoints[i].Longitude;

                                    thisPostcode = thisPostcode.replace(/\s+/g, '');
                                    matchPostcode = matchPostcode.replace(/\s+/g, '');

                                    // if the postcodes match or the lat\lng cords match then group togeather
                                    if (thisPostcode == matchPostcode || (thisLat == matchLat && thisLng == matchLng)) {
                                        this.developmentPoints[j].IsProcessed = true;
                                        matchedArray.push(this.developmentPoints[j]);
                                    }
                                }
                            }

                            // process points
                            if (matchedArray.length > 0) {
                                var plotLat = '';
                                var plotLng = ''

                                // use the first current development lat\lng
                                for (var k = 0; k < matchedArray.length; k++) {
                                    if (matchedArray[k].IsCurrent) {
                                        plotLat = matchedArray[k].Latitude;
                                        plotLng = matchedArray[k].Longitude;
                                    }
                                }

                                // else use the first plot in the collection
                                if (plotLat == '' && plotLat == '') {
                                    plotLat = matchedArray[0].Latitude;
                                    plotLng = matchedArray[0].Longitude
                                }

                                // here we check the development lat, lng and dont draw if not valid
                                if (plotLat && plotLng) {
                                    var point = new GLatLng(plotLat, plotLng);
                                    this._createPoint(point, matchedArray);
                                } else {
                                    // development will not be plotted
                                }

                            } else {
                                alert("error");
                            }
                        }
                        i++;
                    }
                }
            }
        }
    },

    showNoResultPanel: function() {
        ///<summary></summary>
        // var html = '<div id="elNoResults">No developments meatch your search criteria</div>';
        $('elNoResults').style.display = '';
    },

    _afterLoad: function() {
        ///<summary>Perform any after load events</summary>

        // center and zoom
        _exploreMap.map.setZoom(this.map.getBoundsZoomLevel(this.bounds));
        _exploreMap.map.setCenter(this.bounds.getCenter());

        // change opacity of the waiting layer and map
        new Effect.Opacity('exploreMap', { to: 1, duration: 1 });
        new Effect.Opacity('exploreMapWait', { to: 0, duration: 1 });
        $('exploreMapWait').style.display = 'none';
    },


    _createPoint: function(point, devArray) {
        ///<summary></summary>
        ///<remarks>Internal method</remarks>

        // sort the developemts that appear in the tooltip alphabetically
        devArray.sort(alphaSortAsc);

        var dev = devArray[0];

        var ttip = null;
        var html = '';

        if (devArray.length < 2)
            ttip = new ExploreTooltip(dev, this);
        else
            ttip = new ExploreMultiTooltip(devArray, this)

        html = ttip.getHTML();

        var smlMarker = null;

        if (devArray.length > 1) {
            smlMarker = this._createMarker(point, html, this.currentIcon, this.currentAltIcon)
        } else {
            if (dev.IsCurrent == 'true')
                smlMarker = this._createMarker(point, html, this.currentIcon, this.currentAltIcon)
            else
                smlMarker = this._createMarker(point, html, this.futureIcon, this.futureAltIcon)
        }

        this.map.addOverlay(smlMarker);

        this.map.addOverlay(smlMarker.lrgMarker);

        smlMarker.lrgMarker.hide();

        this.bounds.extend(smlMarker.getPoint());

        // RWN UAT Issue #317 - not implemented
        // _exploreMap.map.setZoom(_exploreMap.zoom);

        //this._afterLoad();
    },


    _createMarker: function(point, text, icon, altIcon) {
        ///<summary>Create a marker on the map</summary>
        ///<remarks>Internal method</remarks>
        ///<param name="point"></param>
        ///<param name="html"></param>
        ///<param name="icon"></param>

        var smlMarker = new GMarker(point, icon);
        var lrgMarker = new GMarker(point, altIcon);

        smlMarker.lrgMarker = lrgMarker;
        lrgMarker.smlMarker = smlMarker;

        // add on click event to marker to center map and open tooltip
        GEvent.addListener(lrgMarker, "click", function() {

            // close any current popups
            if (_exploreMap.currentPopup != null)
                _exploreMap.map.removeOverlay(_exploreMap.currentPopup);

            // offset center point to fit in the tooltip
            var newPoint = _exploreMap._getCenterPointOffset(point);
            _exploreMap.map.panTo(newPoint);

            _exploreMap.currentPopup = new EWindow(_exploreMap.map, '1');
            _exploreMap.map.addOverlay(_exploreMap.currentPopup);
            _exploreMap.currentPopup.openOnMarker(smlMarker, text);
        });

        // add mouseover event to change the icon
        GEvent.addListener(smlMarker, "mouseover", function() {

            // ensure small icons are shown for all points
            for (var i = 0; i < _exploreMap.iconCollection.length; i++) {
                if (!_exploreMap.iconCollection[i].lrgMarker.isHidden()) {
                    _exploreMap.iconCollection[i].lrgMarker.hide();
                    _exploreMap.iconCollection[i].show();
                }
            }

            // hide the small marker
            smlMarker.hide();
            // show the large marker
            smlMarker.lrgMarker.show();
        });

        // add mouseout event to reset the icon
        GEvent.addListener(lrgMarker, "mouseout", function() {

            // hide the marker
            lrgMarker.hide();

            // show the small marker
            lrgMarker.smlMarker.show();
        });

        // store ref to marker
        _exploreMap.iconCollection.push(smlMarker);

        return smlMarker;
    },

    _getCenterPointOffset: function(markerPoint) {
        ///<summary>
        /// Returns a point to center the map on offset to fit tooltip into the current viewport
        ///</summary>
        ///<param name="markerPoint">selected marker point</param>
        ///<remarks>Internal method</remarks>

        var agent = navigator.userAgent.toLowerCase();
        var pointX, pointY;
        var offsetX, offsetY;

        offsetX = -0.2;
        offsetY = 0.1;

        if (_exploreMap.map.getZoom() < 10) {
            pointX = markerPoint.x + offsetX;
            pointY = markerPoint.y + offsetY;
        } else {
            pointX = markerPoint.x;
            pointY = markerPoint.y;
        }

        return new GLatLng(pointY, pointX); // n.b Lat before Lng
    },

    clearMap: function() {
        ///<summary>Clear map overlays</summary>
        this.map.clearOverlays();
    },

    removeAll: function() {
        ///<summary>Remove\clear all map overlays\popups</summary>

        if (this.currentPopup != null)
            this.map.removeOverlay(this.currentPopup);
    }
};

function removeAll() {
    ///<summary>Remove\clear all map overlays\popups</summary>
    if(_exploreMap.currentPopup!=null) 
        _exploreMap.map.removeOverlay(_exploreMap.currentPopup);
    return false;
}