﻿var PoiFilter = {
  None: 0,
  Schools: 1,
  ShoppingCentres: 2,
  Parks: 4,
  CommunityFacilities: 8,
  Entertainment: 16,
  Restaurants: 32,
  Recreations: 64,
  HealthCares: 128,
  EmergencyServices: 256,
  Airports: 512,
  PowerStations: 1024,
  RubbishDumps: 2048,
  Cemeteries: 4096,
  TreatmentPlants: 8192,
  CbaBranches: 16384,
  CbaAtms: 32768,
  Jails: 65536,
  HouseStar1: 131072,
  HouseStar2: 262144,
  HouseStar3: 524288,
  HouseStar4: 1048576,
  HouseStar5: 2097152,
  HouseStar0: 4194304
};

var BasePoiMarker = new Class({
  ImageUrl: "",
  ImageWidth: 21,
  ImageHeight: 25,
  ImageShadowUrl: "",
  ImageShadowWidth: 21,
  ImageShadowHeight: 25,
  LatLng: [],
  OnClick: null,
  PoiType: null,
  GMarkerObject: null
});

var PoiTypeCount = new Class({
  PoiTypeID: 0,
  Count: 0
});

var PoiTypeCountArray = new Class({
  CountArray: new Array(),

  // IsTypeInArray: check if a typeId is already in the array
  IsTypeInArray: function(typeId) {
    for (var i = 0; i < this.CountArray.length; i++) {
      if (this.CountArray[i].PoiTypeID == typeId) {
        return true;
      }
    }

    return false;
  },

  // GetCountForType: get the number of POIs registered for the given type
  GetCountForType: function(typeId) {
		for (var i = 0; i < this.CountArray.length; i++) {
			if (this.CountArray[i].PoiTypeID == typeId) {
				return this.CountArray[i].Count;
			}
		}

		return 0;
  },

	// IncrementCountForType: increment the POI count for the given type
	// or create a new PoiTypeCount if the type is not found in the array
	IncrementCountForType: function(typeId) {
		for (var i = 0; i < this.CountArray.length; i++) {
			if (this.CountArray[i].PoiTypeID == typeId) {
				this.CountArray[i].Count++;
				return;
			}
		}

		// if we get here then it means that the type is not found
		// create a new PoiTypeCount
		var typeCount = new PoiTypeCount();
		typeCount.PoiTypeID = typeId;
		typeCount.Count = 1;
		this.CountArray.push(typeCount);
	}
});

var BaseGoogleMapBehaviour = new Class({
    /*
    * GMap2-related
    *
    */

    // back-reference of the actual GMap2 object
    MapObject: null,


    /*
    * POI-related 
    *
    */

    // selected filters
    SelectedFilters: PoiFilter.None,

    // a collection of all GMarkers for pois
    Pois: new Array(),
    Listings: new Array(),

    PoiCounts: new PoiTypeCountArray(),
    ID: '',
    AjaxLoadingDivID: '',
    ItemsBeingLoaded: 0,
    ShowLoading: function(show) {
        if (show) {
            this.ItemsBeingLoaded++;
        }
        else {
            this.ItemsBeingLoaded--;
            if (this.ItemsBeingLoaded < 0) {
                this.ItemsBeingLoaded = 0;
            }
        }
        document.getElementById(this.AjaxLoadingDivID).style.display = this.ItemsBeingLoaded > 0 ? 'block' : 'none';
    },
    CurrentInfoWindowMarker: null,

    // AddPoi: register a poi marker
    AddPoi: function(p) {
        this.SetUpPoi(p);
        this.Pois.push(p);
        this.PoiCounts.IncrementCountForType(p.PoiType);
    },

    AddListing: function(p) {
        this.SetUpPoi(p);
        this.Listings.push(p);
        this.PoiCounts.IncrementCountForType(p.PoiType);
    },

    SetUpPoi: function(p) {
        // create appropriate icon for this poi
        var picon = new GIcon();
        picon.image = p.ImageUrl;
        picon.iconSize = new GSize(p.ImageWidth, p.ImageHeight);

        picon.shadow = p.ImageShadowUrl;
        picon.shadowSize = new GSize(p.ImageShadowWidth, p.ImageShadowHeight);

        picon.iconAnchor = new GPoint(p.ImageWidth / 2, p.ImageHeight);
        picon.infoWindowAnchor = new GPoint(12, 17);

        // create the marker itself
        var pmarker = new GMarker(new GLatLng(p.LatLng[0], p.LatLng[1]), { icon: picon, clickable: true, zIndexProcess: this.CalculatePoiImportance });
        pmarker.Importance = this.GetPoiImportance(p.PoiType);
        GEvent.addListener(pmarker, 'click', p.OnClick);

        // keep this poi in the collection for future references
        p.GMarkerObject = pmarker;
    },

    // GetPoiImportance: this is a function that returns custom google map importance level of a poi to calculate z-indexes, but do not confuse it
    // with the importance level of a poi in the navigators
    GetPoiImportance: function(type) {
        var imp = 0;

        if (type == PoiFilter.HouseStar0 || type == PoiFilter.HouseStar1 || type == PoiFilter.HouseStar2 ||
			 type == PoiFilter.HouseStar3 || type == PoiFilter.HouseStar4 || type == PoiFilter.HouseStar5) {
            switch (type) {
                case PoiFilter.HouseStar0: imp = 1; break;
                case PoiFilter.HouseStar1: imp = 2; break;
                case PoiFilter.HouseStar2: imp = 3; break;
                case PoiFilter.HouseStar3: imp = 4; break;
                case PoiFilter.HouseStar4: imp = 5; break;
                case PoiFilter.HouseStar5: imp = 6; break;
                default: imp = 0;
            }
        }

        return imp;
    },

    // CalculatePoiImportance: this is a custom z-index calculation to overwrite google map's way of calculating z-index. what we
    // are doing here is just using the default behaviour but we add our own importance level of a poi times one million. This is
    // to avoid clash of pois that have close z-indexes.
    CalculatePoiImportance: function(m, b) {
        return GOverlay.getZIndex(m.getPoint().lat()) + (m.Importance * 1000000);
    },

    LoadListings: function() {
        this.ShowLoading(true);

        var currentMapBounds = this.MapObject.getBounds();
        var maxLatLng = currentMapBounds.getNorthEast();
        var minLatLng = currentMapBounds.getSouthWest();

        var fnWrapper = this.FnWrapper(this.OnGetListingsComplete, this);

        Fairfax.Classifieds.Ore.Web.ConsumerWebsite.Controls.Maps.AjaxMapService.GetListings(location.pathname + location.search,
            minLatLng.lat(), minLatLng.lng(), maxLatLng.lat(), maxLatLng.lng(),
            function() {
                var listingsToAdd = arguments[0];
                fnWrapper(listingsToAdd);
            });
    },

    OnGetListingsComplete: function(listingsToAdd) {
        var infoWindow = this.MapObject.getInfoWindow();
        var isInfoWindowOpen = !infoWindow.isHidden();
        var markerWithInfoWindow = null;

        for (var i = 0; i < this.Listings.length; i++) {
            var p = this.Listings[i];
            if (!isInfoWindowOpen || this.CurrentInfoWindowMarker != p.GMarkerObject) {
                this.MapObject.removeOverlay(p.GMarkerObject);
            }
            else {
                //Don't remove this marker or the info window will close
                markerWithInfoWindow = p;
            }
        }

        this.Listings = new Array();

        for (var i = 0; i < listingsToAdd.length; i++) {
            if (markerWithInfoWindow == undefined ||
                (markerWithInfoWindow.LatLng[0] != listingsToAdd[i].Latitude && markerWithInfoWindow.LatLng[1] != listingsToAdd[i].Longitude)) {
                var lstMarker = new BasePoiMarker();
                lstMarker.LatLng = [listingsToAdd[i].Latitude, listingsToAdd[i].Longitude];
                lstMarker.ImageUrl = listingsToAdd[i].ImageUrl;
                lstMarker.ImageWidth = listingsToAdd[i].ImageWidth;
                lstMarker.ImageHeight = listingsToAdd[i].ImageHeight;
                lstMarker.PoiType = listingsToAdd[i].PoiFilterType;

                var p = listingsToAdd[i];
                var fn1 = new Function("OpenListingInfoWinAjax(this, " + p.AdID + ", " + p.Rating + ", " + this.ID + ");");
                lstMarker.OnClick = fn1;
                this.AddListing(lstMarker);
                p.GMarkerObject = lstMarker.GMarkerObject;
            }
        }

        //Re-add marker to list so it will be removed next time
        if (markerWithInfoWindow != undefined) {
            this.Listings.push(markerWithInfoWindow);
            this.PoiCounts.IncrementCountForType(markerWithInfoWindow.PoiType);
        }

        //Displays the filtered listings
        this.FilterListings();

        this.ShowLoading(false);
    },

    FilterListings: function() {
        for (var i = 0; i < this.Listings.length; i++) {
            var p = this.Listings[i];
            if (this.ShouldDisplayPoi(p.PoiType)) {
                this.MapObject.addOverlay(p.GMarkerObject);
            }
            else {
                this.MapObject.removeOverlay(p.GMarkerObject);
            }
        }
    },

    //Webservice call to get the POIs from the DB
    LoadPois: function() {
        if (this.SelectedFilters == PoiFilter.None) {
            this.RemovePois();
            return;
        }

        this.ShowLoading(true);
        var currentMapBounds = this.MapObject.getBounds();
        var maxLatLng = currentMapBounds.getNorthEast();
        var minLatLng = currentMapBounds.getSouthWest();

        var fnWrapper = this.FnWrapper(this.OnGetPoisComplete, this);

        Fairfax.Classifieds.Ore.Web.ConsumerWebsite.Controls.Maps.AjaxMapService.GetPois(this.SelectedFilters,
            minLatLng.lat(), minLatLng.lng(), maxLatLng.lat(), maxLatLng.lng(), 275,
            function() {
                var poisToAdd = arguments[0];
                fnWrapper(poisToAdd);
            });
    },

    RemovePois: function() {
        for (var i = 0; i < this.Pois.length; i++) {
            var p = this.Pois[i];
            this.MapObject.removeOverlay(p.GMarkerObject);
        }
    },

    // OnGetPoisComplete: Ajax callback method for GetPois called from LoadPois
    OnGetPoisComplete: function(poisToAdd) {
        var infoWindow = this.MapObject.getInfoWindow();
        var isInfoWindowOpen = !infoWindow.isHidden();
        var markerWithInfoWindow = null;

        for (var i = 0; i < this.Pois.length; i++) {
            var p = this.Pois[i];
            if (!isInfoWindowOpen || this.CurrentInfoWindowMarker != p.GMarkerObject) {
                this.MapObject.removeOverlay(p.GMarkerObject);
            }
            else {
                //Don't remove this marker or the info window will close
                markerWithInfoWindow = p;
            }
        }
        this.Pois = new Array();

        for (var i = 0; i < poisToAdd.length; i++) {
            if (markerWithInfoWindow == undefined ||
                (markerWithInfoWindow.LatLng[0] != poisToAdd[i].Latitude && markerWithInfoWindow.LatLng[1] != poisToAdd[i].Longitude)) {
                var poiMarker = new BasePoiMarker();
                poiMarker.LatLng = [poisToAdd[i].Latitude, poisToAdd[i].Longitude];
                poiMarker.ImageUrl = poisToAdd[i].ImageUrl;
                poiMarker.ImageWidth = poisToAdd[i].ImageWidth;
                poiMarker.ImageHeight = poisToAdd[i].ImageHeight;
                poiMarker.PoiType = poisToAdd[i].PoiFilterType;

                //make the fn using a string else we lose the reference to name/addr/cba
                var fn1 = new Function(this.ID + ".CurrentInfoWindowMarker = this;OpenPoiInfoWin(this, '" + poisToAdd[i].Name + "', '" + poisToAdd[i].Address + "', " + poisToAdd[i].DisplayCba + ");");
                poiMarker.OnClick = fn1;

                this.AddPoi(poiMarker);
            }
        }

        //Re-add marker to list so it will be removed next time
        if (markerWithInfoWindow != undefined) {
            this.Pois.push(markerWithInfoWindow);
            this.PoiCounts.IncrementCountForType(markerWithInfoWindow.PoiType);
        }

        for (var i = 0; i < this.Pois.length; i++) {
            var p = this.Pois[i];
            this.MapObject.addOverlay(p.GMarkerObject);
        }
        this.ShowLoading(false);
    },

    FnWrapper: function(fn, context) {
        return function() {
            fn.apply(context, arguments);
        };
    },

    // DisplayAllPois: show all poi markers on map
    DisplayAllPois: function() {
        for (var i = 0; i < this.Pois.length; i++) {
            var p = this.Pois[i];
            if (this.ShouldDisplayPoi(p.PoiType)) {
                this.MapObject.addOverlay(p.GMarkerObject);
            }
        }

        for (var i = 0; i < this.Listings.length; i++) {
            var p = this.Listings[i];
            if (this.ShouldDisplayPoi(p.PoiType)) {
                this.MapObject.addOverlay(p.GMarkerObject);
            }
        }
    },

    // SetFilter: set/unset specific filter to be shown/hidden in map
    SetFilter: function(filter, isSet) {
        if (isSet)
            this.SelectedFilters |= filter;
        else
            this.SelectedFilters ^= filter;

        if (filter == PoiFilter.HouseStar0 || filter == PoiFilter.HouseStar1 || filter == PoiFilter.HouseStar2 ||
			 filter == PoiFilter.HouseStar3 || filter == PoiFilter.HouseStar4 || filter == PoiFilter.HouseStar5) {
            this.FilterListings();
        }
        else {
            this.LoadPois();
        }
    },

    // ShouldDisplayPoi: checks if a filter for a specific pois should be rendered on map
    ShouldDisplayPoi: function(filter) {
        var isSelected = false;

        if (this.SelectedFilters == PoiFilter.None)
            isSelected = false;
        else
            isSelected = (this.SelectedFilters & filter) == filter;

        return isSelected;
    },

    RefreshSinglePoiFilter: function(filter) {
        var typeError = document.getElementById("poiFilterErrorMessage-" + filter);

        if (typeError != null) {
            if (!this.PoiCounts.IsTypeInArray(filter)) {
                // the type is not in the array so there is no POI for this type
                typeError.style.color = "#AAA";

                // try to find the label within the item
                var label = typeError.getElementsByTagName("label");

                if (label != null && label.length > 0) {
                    label[0].title = "None found in area";

                    // try to find the checkbox within the label
                    var chk = label[0].getElementsByTagName("input");

                    if (chk != null && chk.length > 0) {
                        chk[0].disabled = true;
                    }
                }

                typeError.disabled = true;
            }
        }
    }
});

function OpenListingInfoWinAjax(marker, adID, rating, behaviour) {
    if (behaviour != undefined) {
        behaviour.ShowLoading(true);
    }
    Fairfax.Classifieds.Ore.Web.ConsumerWebsite.Controls.Maps.AjaxMapService.GetListingWindowDetails(adID,
        function() { OpenListingInfoWinAjaxComplete(arguments[0], rating, marker, behaviour); });
}

function OpenListingInfoWinAjaxComplete(lstInfo, rating, marker, behaviour) {
    OpenListingInfoWin(marker, lstInfo.ThumbnailUrl
, lstInfo.Beds
, lstInfo.Baths
, lstInfo.Cars
, lstInfo.Address
, lstInfo.Price
, lstInfo.AgencyName
, lstInfo.AdTagArea
, lstInfo.AdState
, lstInfo.AdArea
, lstInfo.AdSuburb
, lstInfo.Latitude
, lstInfo.Longitude
, rating
, lstInfo.DetailsUrl
, lstInfo.PhotosUrl
, lstInfo.ShortlistUrl
, lstInfo.EmailFriendUrl
, lstInfo.GetDirectionsUrl
, lstInfo.SuburbProfileUrl
, lstInfo.RecentSalesUrl);

    behaviour.CurrentInfoWindowMarker = marker;
    behaviour.ShowLoading(false);
}
// OpenListingInfoWin: invoke to open infowindow of a GMarker (listing marker) when clicked on map
function OpenListingInfoWin(o, thumb, beds, baths, cars, address, price, agency, /*inspection,*/adTagArea, adState, adArea, adSuburb, lat, lng, rating, detailsUrl, photosUrl, shortlistUrl, emailFriendUrl, getDirectionsUrl, suburbProfileUrl, recentSalesUrl) {
	var subs = {
		"PropertyPhoto": "<img alt=\"\" src=\"" + thumb + "\" />",
		"PropertyType": "propTypeHouse",
		"Bedrooms": beds == "" ? "-" : beds,
		"Bathrooms": baths == "" ? "-" : baths,
		"Carspaces": cars == "" ? "-" : cars,
		"Address": address,
		"DisplayPrice": price,
		"AgencyName": agency,
		//"Inspections": inspection,
		"AdTagArea": adTagArea,
		"AdState": adState,
		"AdArea": adArea,
		"AdSuburb": adSuburb,
		"ViewDetailsUrl": detailsUrl,
		"MorePhotosUrl": photosUrl,
		"ShortlistUrl": shortlistUrl,
		"EmailFriendUrl": emailFriendUrl,
		"GetDirectionUrl": getDirectionsUrl,
		"SuburbProfileUrl": suburbProfileUrl,
		"RecentSalesLink": recentSalesUrl
	};

	// add rating substitution text
	var ratingHtml = "";
	if (rating > 0) {
			ratingHtml = "<div style='border:0;background:none' class='cB-matchList stars-" + rating + "'><b>Matches my preferences:</b><h4 style='margin:0;'><span style='display:block;margin:0;'> </span></h4></div>";
	}
	subs["Rating"] = ratingHtml;

	// substitute variables in srm_html with actual listing data
	var html = listing_html.substitute(subs, /\${([^}]+)}/g);

	// hook into infowindowopen event
	GEvent.addListener(o, 'infowindowopen', initInfoWindow.bind(this, [o, lat, lng]));

	// open window now
	o.openInfoWindowHtml(html);
};

// OpenPoiInfoWin: invoke to open infowindow of a GMarker (poi marker) when clicked on map
function OpenPoiInfoWin(o, name, address, isCba) {
    var cbaSponsorImage = "/ore/Stylesheets/img-components/comm-bank-logo-stack.png";
	var cbaSponsorTrackingUrl = "http://bs.serving-sys.com/BurstingPipe/adServer.bs?cn=tf&amp;c=20&amp;mc=click&amp;pli=1013497&amp;PluID=0&amp;ord=" + PrettyDateTime(new Date());

	var subs = {
		"PoiName": name,
		"PoiAddress": address
	};

	var sponsorshipHtml1 = "";
	var sponsorshipHtml2 = "";
	if(isCba) {
		sponsorshipHtml1 = "<td style='width:130px;padding:5px 0 0 0;vertical-align:top;'><a href='" + cbaSponsorTrackingUrl + "' target='_blank'><img style='border:0' src='" + cbaSponsorImage + "' /></a></td>";
		sponsorshipHtml2 = "<br /><a style='font-size:0.92em;' href='" + cbaSponsorTrackingUrl + "' target='_blank'>More information</a>";
	}
	subs["CbaSponsorship1"] = sponsorshipHtml1;
	subs["CbaSponsorship2"] = sponsorshipHtml2; 

	// substitute variables in srm_poi_html with actual poi data
	var html = poi_html.substitute(subs, /\${([^}]+)}/g);

	// open window now
	o.openInfoWindowHtml(html);
};

// OpenInfoWin: invoke to open infowindow of a GMarker with a specific html string
function OpenInfoWin(o, html) {
	// open window now
	o.openInfoWindowHtml(html);
}

function PrettyDateTime(d) {
	if(d) {
		var day = d.getDay();
		var month = d.getMonth();
		var year = d.getFullYear();
		var hour = d.getHours();
		var minute = d.getMinutes();
		var second = d.getSeconds();
		var tt = "AM";
		if (hour > 11) tt = "PM";
		if (hour > 12) hour = hour - 12;
		if (hour == 0) hour = 12;
		if (hour < 10) hour   = "0" + hour;
		if (minute < 10) minute = "0" + minute;
		if (second < 10) second = "0" + second;

		return day  + '/' + month  + '/' + year + ' ' + hour + ':' + minute + ':' + second + " " + tt;
	}
	
	return '';
}

function SaveMapDefaultPosition(map) {
	if (map && map.savePosition) {
		map.savePosition();
	}
};


function OnMapTypeChanged(sender, args) {
	var map = sender;
	var trackingKey = args;

	var mt = "hybrid";
	switch(map.getCurrentMapType()) {
	case G_SATELLITE_MAP:
		mt = "satellite";
		break;
	case G_HYBRID_MAP:
		mt = "hybrid";
		break;
	default:
		mt = "map";
		break;
	};

	s = s_gi(trackingKey);
	s.linkTrackVars = "prop8,eVar8,event26";
	s.linkTrackEvents = "event26";
	s.prop8 = mt;
	s.eVar8 = mt;
	s.events = "event26";
	s.tl(this, "o", mt);

	Cookie.write("bgm.MapType", mt, {domain: document.domain, path: "/", duration: 365});
}

if (typeof (Sys) !== 'undefined') {
	Sys.Application.notifyScriptLoaded();
};