

var map;

var m_pntSouthWest;
var m_pntNorthEast;
var m_bounds = null;

var markerCount = 0;
var m_markers = [];

var m_iconBlue = null;
var m_iconRed = null;

var m_hasGoogleMaps = false;

var m_elMarkerTabLoading;
var m_elMarkerTabError;

if (window.attachEvent)
{
	//ie method
	window.attachEvent("onload", loadMap);
}
else if (window.addEventListener)
{
	//firefox method
	window.addEventListener("load", loadMap, false);
}

function loadMap()
{
  var elMap = document.getElementById("searchResults_map");
  
  if (!elMap)
  {
	return;
  }

  try
  {
	m_hasGoogleMaps = GBrowserIsCompatible();
  }
  catch (e) {}
	
  var elSearchResults = document.getElementById("searchResults");
  var elSearchEmptyResults = document.getElementById("searchEmptyResults");
  
  //21-dec-2007 markg: now set the bounds first. this determines if we show a map or not
  setBounds();
  
  //should we not display the map?
  if (!m_bounds)
  {
	elSearchEmptyResults.style.display = "block";
	
	document.getElementById("searchResults_mapColumn").style.display = "none";
	document.getElementById("searchResults_list_results").style.display = "none";
	elSearchResults.style.display = "block";
  }

  //do we have google maps at all?
  if (!m_hasGoogleMaps)
  {
	elSearchEmptyResults.innerHTML = "Could not connect to Google Maps. Please try again.";
	elSearchEmptyResults.style.color = "red";
	elSearchEmptyResults.style.fontWeight = "bold";
	
	elSearchResults.style.display = "block";
  }
  
  //do we have some results?
  if (m_hasGoogleMaps && m_bounds)
  {
    elSearchResults.style.display = "block";
  
    map = new GMap2(elMap);

    map.addControl(new GLargeMapControl());
    //map.addControl(new GScaleControl());

    //markg: don't need the option to change to satellite view
    //map.addControl(new GMapTypeControl());

    //add map overview
    map.addControl(new GOverviewMapControl(new GSize(100, 100)));

    setBounds();
    
	m_zoomLevel = map.getBoundsZoomLevel(m_bounds);

	map.setCenter(m_bounds.getCenter(), m_zoomLevel);
	
	//load the global marker tab (loading and error)
	m_elMarkerTabLoading = document.getElementById("markerLoading");
	m_elMarkerTabError = document.getElementById("markerError");

	addMarkers();

	if (window.attachEvent)
	{
		window.attachEvent('onunload', unloadMap);
	}
	else if (window.addEventListener)
	{
		window.addEventListener("unload", unloadMap, false);
	}
	
	//21-dec-2007 markg: mozilla maintains the filter values between a refresh, so do a quick update on load
	performMapUpdateFilter();
  }
  
}

function doStuff()
{
	var zoom = map.getZoom();
	
	if (zoom >= 14)
	{
		var bounds = map.getBounds();
		
		//refresh the page, based on this bounds
		var chkCentreTypes = getCentreTypeCheckboxes();
		
		var ctype = "";
		
		var isFirst = true;
		
		for (var i = 0; i < chkCentreTypes.length; i++)
		{
			var chkCentreType = chkCentreTypes[i];
			
			if (chkCentreType)
			{
				if (isFirst)
				{
					isFirst = false;
				}
				else
				{
					ctype += ",";
				}
				
				ctype += chkCentreType.attributes.centreTypeId.nodeValue;
			}
		}
		
		var url = "/search/ccresults.asp?ctype=" + ctype;
		
		url += "&w=" + bounds.getSouthWest().lng();
		url += "&s=" + bounds.getSouthWest().lat();
		url += "&e=" + bounds.getNorthEast().lng();
		url += "&n=" + bounds.getNorthEast().lat();
		
		//10-jan-2008 markg: include the search query when doing a spatial search, to return to the super search results page
		var txtQuery = document.getElementById("txtQuery");
		
		if (txtQuery && txtQuery.value.length > 0)
		{
			url += "&query=" + txtQuery.value;
		}
		
		window.location = url;
	}
	else
	{
		alert('The map is too far out to update. Please zoom in closer and try again.');
	}
}

function unloadMap()
{
	try
	{
		GUnload();
	}
	catch (e)
	{ }
}

function buildMarkerKey(id)
{
    return "marker" + id;
}

function createIcon(imageName)
{
	var icon = new GIcon();

	//c4k map pins
	icon.image = imageName;
	icon.iconSize = new GSize(16, 32);
	icon.iconAnchor = new GPoint(8, 32);
	icon.infoWindowAnchor = new GPoint(8, 1);
	icon.imageMap = [0,0,0,31,31,31,31,0];

	icon.shadow = "/search/images/pin_shadow.png";
	icon.shadowSize = new GSize(37, 32);

	/*
	 * old realmap coords
	 *
	icon.image = imageName;
	icon.iconSize = new GSize(15, 27);
	icon.iconAnchor = new GPoint(8, 27);
	icon.infoWindowAnchor = new GPoint(8, 1);
	icon.imageMap = [0,0,0,27,27,27,27,0];
	 */

	return icon;
}

function createMarker(id, x, y, title, hasVacancy, hasCentrePrices)
{
	//does the marker have a valid lat long
	var hasLocation = x && y;
	
	var markerOpts = {}; //{"title" : title };
	
	if (hasLocation)
	{
		//create icons if necessary
		if (!m_iconBlue)
		{
			m_iconBlue = createIcon("/search/images/blue_pin.png");
			m_iconRed = createIcon("/search/images/red_pin.png");
		}

		markerOpts.icon = m_iconBlue;

		if (hasVacancy)
		{
			markerOpts.icon = m_iconRed;
		}
	}
	
	var pnt = new GLatLng(y, x);
	var marker = new GMarker(pnt, markerOpts);

    marker.id = id;
    marker.title = title;
    marker.hasLocation = hasLocation;
    
    //default marker to invisible
    marker.visible = false;
    
    marker.hasVacancy = hasVacancy;
    marker.hasCentrePrices = hasCentrePrices;

    var elItem = document.getElementById("item" + id);

    marker.elItem = elItem;

	if (hasLocation)
	{
	
		//add some events on the google maps marker
		GEvent.addListener(marker, "click",
			function()
			{
				marker.showMarkerWindow(true /* scrollIntoView */);
			});

		GEvent.addListener(marker, "mouseover",
			function()
			{
				highlightResult(id);
			});

		GEvent.addListener(marker, "mouseout",
			function()
			{
				unhighlightResult(id);
			});
    }
        
    //add some methods to the marker
    marker.hide = marker_hide;
    marker.show = marker_show;
    marker.toggleVisible = marker_toggleVisible;
    marker.showMarkerWindow = marker_showMarkerWindow;
    marker.matchesVacancy = marker_matchesVacancy;
    marker.matchesCentreType = marker_matchesCentreType;
    marker.matchesAgeGroup = marker_matchesAgeGroups;
    marker.findInfoTabs = marker_findInfoTabs;
    marker.showInfoWindowTabs = marker_showInfoWindowTabs;
    marker.showLoadingTab = marker_showLoadingTab;
    marker.showErrorTab = marker_showErrorTab;
    marker.getWeeklyScheduleForAge = marker_getWeeklyScheduleForAge;

	//show the marker by default
    marker.show();

    var key = buildMarkerKey(id);

	//index marker by key
    m_markers[key] = marker;
    
    //also add marker to array
    m_markers.push(marker);
    
    return marker;
}

	function marker_showLoadingTab()
	{
		if (m_elMarkerTabLoading)
		{
			var infoTabs = [];
			
			infoTabs[0] = new GInfoWindowTab("Loading...", m_elMarkerTabLoading.innerHTML);
			
			this.showInfoWindowTabs(infoTabs);
		}
	}
	
	function marker_showErrorTab()
	{
		if (m_elMarkerTabError)
		{
			var infoTabs = [];
			
			infoTabs[0] = new GInfoWindowTab("Error", m_elMarkerTabError.innerHTML);
			
			this.showInfoWindowTabs(infoTabs);
		}
	}
	
	function marker_showInfoWindowTabs(infoTabs)
	{
		//show the info tabs
		var infoWindowOpts = {"maxWidth" : 250};
		
		//2008-jun-24 markg: allow more space for the new fees tab
		if (infoTabs.length >= 4)
		{
			infoWindowOpts.maxWidth = 350;
		}
		
		this.openInfoWindowTabsHtml(infoTabs, infoWindowOpts);
	}

	function marker_findInfoTabs()
	{
		//setup the marker google map pop-up tabs
		var infoTabs = null;

		var id = this.id;

		var markerEl = document.getElementById("markerInfo" + id);

		if (markerEl)
		{
			infoTabs = [];
			
			infoTabs[0] = new GInfoWindowTab("Details", markerEl.innerHTML);
	    
			if (this.hasVacancy)
			{
				var markerVacancyEl = document.getElementById("markerInfo_Vacancies" + id);

				infoTabs[infoTabs.length] = new GInfoWindowTab("Vacancies", markerVacancyEl.innerHTML);
			}
			
			if (this.hasCentrePrices)
			{
				var markerCentrePriceEl = document.getElementById("markerInfo_Fees" + id);
				
				infoTabs[infoTabs.length] = new GInfoWindowTab("Fees", markerCentrePriceEl.innerHTML);
			}
			
			var markerTestimonialsEl = document.getElementById("markerInfo_Testimonials" + id);
			
			infoTabs[infoTabs.length] = new GInfoWindowTab("Testimonials", markerTestimonialsEl.innerHTML);
		}
		
		//save the infotabs (if any) with this marker
		this.infoTabs = infoTabs;
	}

	function marker_showMarkerWindow(scrollIntoView /*should the list item be scrolled into view as well*/)
    {
		if (scrollIntoView && this.elItem)
		{
			this.elItem.scrollIntoView(false);
		}
		
		if (this.hasLocation)
		{
			//does this marker have info tabs loaded?
			if (!this.infoTabs)
			{
				//look in the document
				this.findInfoTabs();
			}
			
			//were the infotabs found in the document?
			if (!this.infoTabs)
			{
				this.showLoadingTab();
				
				//load the info tabs using ajax
				ajaxGetCentreMapTabs(this);
			}
			else
			{
				this.showInfoWindowTabs(this.infoTabs);
			}
		}
    }
    
    //2008-03-14 markg: wraps up Daragh's GetXmlHttpObject() with a container
    // object, for storing an argument when invoking the callback function
    function executeAjax(url, formVariables, callback, callbackArg)
    {
		var container = {};
		container.callbackArg = callbackArg;
		container.callback = callback;
		
		container.doCallback = function()
		{
			container.callback(container.callbackArg);
		};
		
		var xhttp = GetXmlHttpObject(container.doCallback);
		
		container.xhttp = xhttp;
		
		xhttp.open ("POST", url , true /* async */);
		xhttp.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded");
		xhttp.send (formVariables);
		
		return container;
    }
    
    function ajaxGetCentreMapTabs(marker)
    {
		if (!marker)
		{
			return;
		}
		
		var url = "/search/GetCentreMapTabs.asp";
		var fvars = "id=" + marker.id;
		
		//2008-jul-8 markg: now include the search query string when querying for map tab information.
		// these querystrings are used by the minisite version of the centre profile page
		// to provide the user with a "return to search listings" button.
		if (c4k.getSearchQueryString)
		{
			var searchQueryString = c4k.getSearchQueryString();
			
			if (searchQueryString && searchQueryString.length > 0)
			{
				fvars += "&" + searchQueryString;
			}
		}
		
		executeAjax(url, fvars, onGetCentreMapTabs, marker);
    }
    
    function onGetCentreMapTabs(marker)
    {
		if (this.xhttp.readyState == 4 || this.xhttp.readyState == "complete")
		{
			//was the ajax call successful?
			if (this.xhttp.status == 200)
			{
				var elContainer = document.createElement("div");
				elContainer.innerHTML = this.xhttp.responseText;
				
				var elMarkerInfo = document.getElementById("searchResults_markerInfo");
				
				elMarkerInfo.appendChild(elContainer);
				
				//check the marker has info tabs now
				marker.findInfoTabs();
				
				//no info tabs still?
				if (!marker.infoTabs)
				{
					//probably an error loading. show an error and stop, instead of recursively firing of another ajax
					// request
					marker.showErrorTab();
				}
				else
				{				
					//after loading the marker html into the document, show the window
					marker.showMarkerWindow();
				}
			}
			else
			{
				marker.showErrorTab();
			}
		}
    }

	function marker_show()
	{
		//is the marker not visible?
		if (!this.visible)
		{
			if (this.hasLocation)
			{
				map.addOverlay(this);
			}
			
			if (this.elItem)
			{
				this.elItem.style.display = '';
			}
			
			this.visible = true;
		}
	}
	
	function marker_hide()
    {
		//is the marker visible?
		if (this.visible)
		{
			if (this.hasLocation)
			{
				map.removeOverlay(this);
			}
			
			this.elItem.style.display = 'none';
			
			this.visible = false;
		}
    }
    
    function marker_toggleVisible(visible)
    {
		//already in the desired visible state?
		if (this.visible == visible)
		{
			//bail
			return;			
		}
		
		//is the marker currently visible?
		if (this.visible)
		{
			this.hide();
		}
		else
		{
			this.show();			
		}
    }
    
    function marker_matchesVacancy(hasVacancy)
    {
		return this.hasVacancy == hasVacancy;
    }
    
    function marker_matchesCentreType(centreType)
    {
		var matches = false;
		
		for (var i = 0; i < this.centreTypes.length; i++)
		{
			var currentCentreType = this.centreTypes[i];
			
			matches = currentCentreType == centreType;
			
			if (matches)
			{
				break;
			}
		}
		
		return matches;
    }
    
    
    ///////// highlight/unhighlight of marker

    var m_label = null;

    function highlightResult(id)
    {
        var el = document.getElementById("item" + id);

        if (el)
        {
			el.style.backgroundColor = "ECF1F9";
		}

        //clean-up old label
        if (m_label)
        {
            map.removeOverlay(m_label);
            m_label = null;
        }

        var marker = m_markers[buildMarkerKey(id)];

        if (marker)
        {
			m_label = new ELabel(marker.getPoint(), marker.title, "searchResults_map_label", new GSize(10, 10), 80);

			map.addOverlay(m_label);
		}
    }

    function unhighlightResult(id)
    {
        var el = document.getElementById("item" + id);

        if (el)
        {
			el.style.backgroundColor = "";
		}

        //clean-up label
        if (m_label)
        {
            //map.removeTLabel(m_label);
            map.removeOverlay(m_label);
            m_label = null;
        }
    }

function getMarker(id)
{
	var key = buildMarkerKey(id);
	
	var marker = m_markers[key];
	
	return marker;
}

function showMarker(id)
{
	var marker = getMarker(id);
	
	if (marker)
	{
		marker.showMarkerWindow();
	}
}

var _chkCentreTypes = null;

function getCentreTypeCheckboxes()
{
	if (!_chkCentreTypes)
	{
		//22-dec-2007 markg: if the number of centretypes exceeds this number, they won't be included in the filter
		var centreTypesMaximum = 40;
		
		var chkCentreTypes = [];
		
		for (var i = 1; i <= centreTypesMaximum; i++)
		{
			var chkCentreType = document.getElementById('chkCentreType' + i);
			
			if (chkCentreType)
			{
				chkCentreTypes.push(chkCentreType);
			}
		}
		
		_chkCentreTypes = chkCentreTypes;		
	}

	return _chkCentreTypes;
}

var _chkDays = null;

function getDaysCheckboxes()
{
	if (!_chkDays)
	{
		_chkDays = {};
		
		_chkDays[2] = document.getElementById('chkMon');
		_chkDays[3] = document.getElementById('chkTues');
		_chkDays[4] = document.getElementById('chkWed');
		_chkDays[5] = document.getElementById('chkThurs');
		_chkDays[6] = document.getElementById('chkFri');
	}
	
	return _chkDays;
}

var m_mapRefiningTimer = null;

function mapUpdateFilter()
{
	//clear any timers to update the map
	clearDelayedMapFilterUpdate();
	
	//map is not refining?
	if (!m_mapRefiningTimer)
	{
		//show refining overlay
		toggleRefiningOverlay(true);
		
		//show the refining box for 2secs, then search the map
		m_mapRefiningTimer = window.setTimeout("performMapUpdateFilter()", 750);
	}
}

function clearMapRefiningTimer()
{
	if (m_mapRefiningTimer)
	{
		window.clearTimeout(m_mapRefiningTimer);
		m_mapRefiningTimer = null;
	}
}

function toggleRefiningOverlay(visible)
{
	var elRefiningOverlay = document.getElementById("searchOverlay");
	
	if (elRefiningOverlay)
	{
		if (visible)
		{
			elRefiningOverlay.style.display = 'block';
		}
		else
		{
			elRefiningOverlay.style.display = 'none';
		}
	}
}

function performMapUpdateFilter()
{
	//clear the refining timer
	clearMapRefiningTimer();
	
	//hide refining overlay
	toggleRefiningOverlay(false);
	
	var chkShowOnlyVacancies = document.getElementById('chkFilterShowOnlyVacancies');

	//is there a chkFilterShowOnlyVacancies checkbox? is this super search map?
	if (!chkShowOnlyVacancies)
	{
		return;
	}

	//get the centre types user has selected
	var chkCentreTypes = getCentreTypeCheckboxes();
	
	//get the vacancy info the user has selected
	var showOnlyCentresWithVacancies = chkShowOnlyVacancies.checked;
	
	var chkDays = getDaysCheckboxes();
	
	var filterSchedule = new c4k.WeeklySchedule();
	
	for (var i = 2; i <= 6; i++)
	{
		filterSchedule.days[i] = chkDays[i].checked;
	}
	
	var filterAge = null;
	
	var txtFilterAge = document.getElementById("txtFilterAge");
	var ddlFilterAgeType = document.getElementById("ddlFilterAgeType");
	
	var days = parseInt(txtFilterAge.value);
	
	if (!isNaN(days))
	{
		days *= ddlFilterAgeType.value;
		
		filterAge = c4k.TimeSpan.createFromDays(days);
	}
	
	//now find the centres that match the filter
	var markersShownCount = 0;
	
	var bounds = null;
	
	//variables for green-shading the matching results to the user
	var combinedScheduleForAge = null;
	var combinedCentreTypes = [];
	
	//loop through markers
	for (var i = 0; i < m_markers.length; i++)
	{
		var marker = m_markers[i];
		
		var matchesVacancyFilter = marker.matchesAgeGroup(filterAge, filterSchedule, showOnlyCentresWithVacancies);
		
		var matchesCentreTypeFilter = null;
		
		for (var j = 0; j < chkCentreTypes.length; j++)
		{
			var chkCentreType = chkCentreTypes[j];
			
			if (chkCentreType)
			{
				var centreTypeId = chkCentreType.attributes.centreTypeId;
				
				//did we find the attribute?
				if (centreTypeId)
				{
					centreTypeId = centreTypeId.nodeValue;
				}
				else
				{
					alert("*** internal error: centre type checkbox should have a centreTypeId attribute ***");
				}
				
				var matches = (chkCentreType.checked && marker.matchesCentreType(centreTypeId));
				
				if (!matchesCentreTypeFilter)
				{
					matchesCentreTypeFilter = matches;
				}
				else
				{
					matchesCentreTypeFilter = matchesCentreTypeFilter || matches;
				}
				
				//if we've found a match for centre type, we can bail out early
				if (matches)
				{
					break;
				}
			}
		}
			
		var shouldBeVisible = matchesVacancyFilter && matchesCentreTypeFilter;
		
		marker.toggleVisible(shouldBeVisible);
		
		if (shouldBeVisible)
		{
			markersShownCount++;
			
			if (marker.hasLocation)
			{
				var pnt = marker.getPoint();
				
				if (!bounds)
				{
					bounds = new GLatLngBounds(pnt, pnt);
				}
				else
				{
					bounds.extend(pnt);
				}
			}
			
			//2008-04-23 markg: update the combined weekly schedule for this age, as well as matching centre types
			// for the purposes of green-shading the matches to the user
			var ageWeeklySchedule = marker.getWeeklyScheduleForAge(filterAge);
			
			if (!combinedScheduleForAge)
			{
				combinedScheduleForAge = ageWeeklySchedule;
			}
			else
			{
				combinedScheduleForAge.union(ageWeeklySchedule);
			}
			
			for (var j = 0; j < marker.centreTypes.length; j++)
			{
				var centreType = marker.centreTypes[j];
				
				//mark this centre type as included in the combined list
				combinedCentreTypes[centreType] = true;
			}
		}
	}
	
	var isRefined;
	
	//2008-04-23 markg: highlight the days checkboxes that match the refined search
	for (var i = 2; i <= 6; i++)
	{
		var dayName = chkDays[i].id.replace('chk', '');
		var label = document.getElementById('lbl' + dayName);
		
		if (label)
		{
			isRefined = combinedScheduleForAge !== null && combinedScheduleForAge.getDay(i) && chkDays[i].checked;
			
			toggleRefinedMatchOfElement(label, isRefined);
		}
	}
	
	//2008-04-23 markg: highlight the child age textbox, if their are some matching schedules
	isRefined = combinedScheduleForAge !== null && !combinedScheduleForAge.daysAllFalse();
	toggleRefinedMatchOfElement(txtFilterAge, isRefined);

	//2008-04-23 markg: highlight the centre type checkboxes that match the refined search
	
	//loop through all centre type checkboxes
	for (var i = 0; i < chkCentreTypes.length; i++)
	{
		//get the actual centre type number
		var chkCentreType = chkCentreTypes[i];
		
		var centreTypeId = chkCentreType.attributes.centreTypeId;
		
		if (centreTypeId)
		{
			centreTypeId = centreTypeId.nodeValue;
		}
		
		//is it a valid number?
		if (centreTypeId)
		{
			//find the corresponding label
			var lblCentreType = document.getElementById('lblCentreType' + centreTypeId);
			
			//label found?
			if (lblCentreType)
			{
				//is the current centre type shown in the list and is it ticked?
				isRefined = combinedCentreTypes[centreTypeId] && chkCentreType.checked;
				
				//refine the element
				toggleRefinedMatchOfElement(lblCentreType, isRefined);
			}
		}
	}
	
	if (bounds)
	{
		var zoomLevel = map.getBoundsZoomLevel(bounds);
		
		//22-dec-2007 markg: having the map zoom around automatically when filtering is a bit annoying
		// as a user, i tend to lose track of the area i was interested in, especially when panning
		// and doing a spatial search.
		//map.setCenter(bounds.getCenter(), zoomLevel);
	}
	
	//update count
	var spanResultsFound = document.getElementById('spanResultsFound');
	
	spanResultsFound.innerHTML = markersShownCount;
}

/* 8-may-2008 markg: functions to handle toggling the refined status of elements, by appending an extra class name */
function toggleRefinedMatchOfElement(el, isRefined)
{
	if (!el)
	{ return; }
	
	if (!isRefined)
	{
		//8-may-2008 markg: must explicity set it to false, to guard against javascript values such as undefined and null, so
		//  that the compare for change below doesn't trigger when it really shouldn't
		isRefined = false;
	}
	
	//is this the first time the element has been refine toggled?
	if (!el.refinedMatch)
	{
		el.refinedMatch = {};
		el.refinedMatch.isRefined = false;
		
		//save old class name
		el.refinedMatch.oldClassName = el.className;
		
		//set old class name to empty string if none
		if (!el.refinedMatch.oldClassName)
		{
			el.refinedMatch.oldClassName = '';
		}
	}
	
	//is the elements refined match status changing?
	if (el.refinedMatch.isRefined != isRefined)
	{
		//time to show refined?
		if (isRefined)
		{
			el.className = el.refinedMatch.oldClassName + ' searchResults_refinedMatch';
		}
		//time to hide refined?
		else
		{
			el.className = el.refinedMatch.oldClassName;
		}
		
		el.refinedMatch.isRefined = isRefined;
	}	
}


/* 21-dec-2007 markg: starts a delayed map update. used for textboxes when typing in fields */
var mapFilterUpdateTimer = null;

function clearDelayedMapFilterUpdate()
{
	if (mapFilterUpdateTimer)
	{
		window.clearTimeout(mapFilterUpdateTimer);
		mapFilterUpdateTimer = null;
	}
}

function startDelayedMapFilterUpdate()
{
	clearDelayedMapFilterUpdate();
	
	mapFilterUpdateTimer = window.setTimeout("mapUpdateFilter();", 1000);
}


/********************** vacancy ****************/


c4k = {};

c4k.TimeSpan = {};
c4k.TimeSpan.createFromDays = function(/*int*/ days)
{
    var span = new AjaxControlToolkit.TimeSpan(days, 0 /*hrs*/, 0 /*mins*/, 0 /*secs*/);
    
    return span;
};

c4k.TimeRange = function(/*TimeSpan*/ from, /*TimeSpan*/ to)
{
    this.from = from;
    this.to = to;
};

c4k.TimeRange.prototype.isInRange = function(/*TimeSpan*/ time)
{
    if (!time)
    {
        return false;
    }
        
    var greaterThanFrom = time.compareTo(this.from) >= 0;
    
    if (!greaterThanFrom)
    {
        return false;
    }
    
    var lessThanTo = time.compareTo(this.to) <= 0;
    
    return lessThanTo;
};

c4k.WeeklySchedule = function(/*bool[8] - for days 1 - 7 */ days)
{
    if (!days)
    {
        days = {};
    }
        
    this.days = days;
};

c4k.WeeklySchedule.prototype.getDay = function(/*int*/ dayNum)
{
    if (!dayNum)
    {
        return false;
    }
        
    var hasDay = this.days[dayNum];
    
    if (hasDay)
    {
        return true;
    }
    
    return false;
};

//tests whether two weekly schedules overlap at all
c4k.WeeklySchedule.prototype.overlapsWith = function(/*WeeklySchedule*/ schedule)
{
    if (!schedule)
    {
        return false;
    }
        
    //loop through all days in this schedule
    for (var i = 1; i <= 7; i++)
    {
        var hasDay = this.getDay(i);
        
        //does this schedule include this day?
        if (hasDay)
        {
            var otherHasDay = schedule.getDay(i);
            
            //does the other schedule have this day?
            if (otherHasDay)
            {
                //then the schedules overlap - work is done
                return true;
            }
        }
    }
    
    //if we get this far, then the schedules don't overlap
    return false;
};

//returns true if all the schedule days are false
c4k.WeeklySchedule.prototype.daysAllFalse = function()
{
	var allFalse = true;

	for (var i = 1; i <= 7; i++)
	{
		if (this.getDay(i))
		{
			allFalse = false;
			break;
		}
	}
	
	return allFalse;
};

c4k.WeeklySchedule.prototype.union = function(/*WeeklySchedule*/ other)
{
	if (!other)
	{
		return;
	}
	
	for (var i = 1; i <= 7; i++)
	{
		this.days[i] = this.getDay(i) || other.getDay(i);
	}
};

c4k.WeeklySchedule.prototype.copy = function()
{
	var days = {};
	
	for (var i = 1; i <= 7; i++)
	{
		days[i] = this.getDay(i);
	}
	
	return new c4k.WeeklySchedule(days);
};


//vacancy ctor
c4k.Vacancy = function(/*TimeRange*/ ageRange, /*WeeklySchedule*/ schedule)
{
    this.ageRange = ageRange;
    this.schedule = schedule;
};

c4k.Vacancy.prototype.hasVacancyFor = function(/*TimeSpan*/ age, /*WeeklySchedule*/ schedule)
{
    var hasVacancy = true;
    
    if (age)
    {
        hasVacancy = this.ageRange.isInRange(age);
    }
    
    if (hasVacancy && schedule)
    {
        hasVacancy = this.schedule.overlapsWith(schedule);
    }
    
    return hasVacancy;
};


function marker_matchesAgeGroups(age, schedule, showOnlyCentresWithVacancies)
{
	//are we including all centres, even without matching vacancies?
	if (!showOnlyCentresWithVacancies)
	{
		return true;
	}

    var vacancies = this.vacancies;
    
    //has vacancies?
    var hasVacancies = vacancies && vacancies.length > 0;
    
	//must also check if all the vacancy age group entries have no days ticked.
	// if so, them simply assume no vacancy information and handling accordingly
	var allVacanciesHaveNoSchedule = true;		
    
    if (hasVacancies)
    {
        for (var i = 0; i < vacancies.length; i++)
        {
            var vacancy = vacancies[i];
            
            allVacanciesHaveNoSchedule = allVacanciesHaveNoSchedule && vacancy.schedule.daysAllFalse();
            
            //does the vacancy match?
            var matches = vacancy.hasVacancyFor(age, schedule);
            
            if (matches)
            {
                return true;
            }
        }
    }
  
	//no matching vacancy found
    return false;
}

function marker_getWeeklyScheduleForAge(age)
{
	var completeSchedule = null;

	var vacancies = this.vacancies;
    
    //has vacancies?
    var hasVacancies = vacancies && vacancies.length > 0;
    
    if (hasVacancies)
    {
		for (var i = 0; i < vacancies.length; i++)
		{
			var vacancy = vacancies[i];
			
			//vacancy supports requested age?
			if (vacancy.ageRange.isInRange(age))
			{			
				//first vacancy?
				if (!completeSchedule)
				{
					//simply copy it
					completeSchedule = vacancy.schedule.copy();
				}
				else
				{
					//otherwise union it into the result
					completeSchedule.union(vacancy.schedule);
				}
			}
		}
	}
	
	return completeSchedule;
}



/*>>>>>>>>>>>>>>>>>>>>>>> used by super search /search/ccresults.asp */
//>>> i slade javascript
	
		function superLoad()
		{
			//toggleSearch('yes');
			
			var elMap = document.getElementById('searchResults_map');
			
			if (elMap)
			{
				elMap.style.width = '570px';
			}
			
			var elMapColumn = document.getElementById('searchResults_mapColumn');
			
			if (elMapColumn)
			{
				elMapColumn.style.width = '570px';
			}
		}

		
		
		var hideTip = null;
	
		function toggleSearch(loadID) {
			/*if (document.getElementById) {
				var ssOP = document.getElementById('ssPanel');
				var ssSt = document.getElementById('sscTitle');
				
				if (ssOP.style.display == '') {
					ssOP.style.display = 'none';
					ssSt.style.display = '';
				}else{
					ssOP.style.display = '';
					ssSt.style.display = 'none';
				}
			}*/
			if (loadID == "yes") {
				//display tip
				var ssTip = document.getElementById('ssTip');
				ssTip.style.display = '';
				hideTip = setInterval("tipTimer()", 10000);
			}
			
			//2008-03-20 markg: so the toggle click doesn't actually change the browser at all
			return false;
		}
		
		function tipTimer() {
			var ssTip = document.getElementById('ssTip');
			ssTip.style.display = 'none';
			clearInterval(hideTip);
			
			hideTip = null;
		}
		
		function toggleTip() {
			if (document.getElementById) {
				var ssTip = document.getElementById('ssTip2');
				if (ssTip.style.visibility == 'hidden') {
					ssTip.style.visibility = 'visible';
				}else{
					ssTip.style.visibility = 'hidden';
				}
			}
		
		}
		//<<< end i slade javascript
		
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<< end used by supersearch: /search/ccresults.asp */