var CompanyPanel = function () {
	this.companies = [];
	this.results = null; // We want to keep a reference around
}

CompanyPanel.prototype.paint = function () {
	this.companyList = UL({"class":"menu"});
	this.element = DIV({"class":"companyPanel"}, this.companyList);

	return this.element;
}

CompanyPanel.prototype.setResults = function (results) {
	this.results = results;
	this.jobs = results.results;
	this.analyzeCompanies();
	this.renderCompanies();
}

CompanyPanel.prototype.clearCompanies = function () {
	while (this.companyList.firstChild != null) {
		this.companyList.removeChild (this.companyList.firstChild);
	}
}

CompanyPanel.prototype.analyzeCompanies = function () {
	this.companies = [];

	// Create the "All Companies" link
	this.companies['All Companies'] = {
		name: 'All Companies',
		url: null,
		icon: null,
		jobs: this.jobs
	};

	for (var i=0; i < this.jobs.length; i++) {
		if (!this.companies[this.jobs[i].companyName]) {
			this.companies[this.jobs[i].companyName] = {
				name: this.jobs[i].companyName,
				url: this.jobs[i].companyLink,
				icon: this.jobs[i].companyLogo,
				jobs: []
			};
		}
		this.companies[this.jobs[i].companyName].jobs.push (this.jobs[i]);
	}
}

CompanyPanel.prototype.renderCompanies = function () {
	this.clearCompanies();
	var companyNames = this.getSortedCompanyNames();
	for (var i=0; i < companyNames.length; i++) {
		this.renderCompany(companyNames[i]);
	}
}

CompanyPanel.prototype.renderCompany = function (companyName) {
	var link = A({href:"javascript:void(0);"}, companyName);
	link.onclick = bind(this.showCompanyJobs, this);

	var style = null;
	if (companyName == 'All Companies') {
		style = {"class":"active"};
		this.activeLink = link;
	}

	var li = LI(style, link, " ( " + this.companies[companyName].jobs.length + " )");

	this.companyList.appendChild (li);
}

CompanyPanel.prototype.getSortedCompanyNames = function () {
	var arr = [];
	var idx = 0;

	for (var key in this.companies) {
		//alert ("key: " + key);
		arr[idx++] = key;
	}

	// Start at idx 1 to offset "All Companies"
	for (var i=1; i < arr.length; i++) {
		for (var j=i+1; j < arr.length; j++) {
			if (arr[j] < arr[i]) {
				var tmp = arr[i];
				arr[i] = arr[j]
				arr[j] = tmp;
			}
		}
	}

	// We'll need to ensure that 'All Companies' is first at some point.

	return arr;
}

CompanyPanel.prototype.showCompanyJobs = function (e) {
	var target, companyName;

	if (e != undefined) {
		target = e.target;
		companyName = target.textContent;
	} else {
		target = window.event.srcElement;
		companyName = target.firstChild.nodeValue;
	}

	var allCompanies = (companyName == 'All Companies') ? true : false;

	this.activeLink.setAttribute ("class", "default");
	this.activeLink.setAttribute ("className", "default");
	target.setAttribute ("class", "active");
	target.setAttribute ("className", "active");
	
	this.activeLink = target;
	this.activeCompany = companyName;

	var searchResults = {
		resultCount: ((allCompanies) ? this.results.resultCount : this.companies[companyName].jobs.length),
		results: this.companies[companyName].jobs,
		skills: ((allCompanies) ? this.results.skills : []),
		processingTime: 0.0,
		stale: !allCompanies		// Indicate that this result set is not to be passed around!
	};

	signal (this, "viewResults", searchResults);
}

CompanyPanel.prototype.getActiveCompanyName = function () {
	return this.activeCompany;
}
var DiceContext = function (name) {
	this.name = name;
	this.currentPage = 1;
	this.pageSize = 5;
	this.sortMethod = 'date';
	this.registry = new SkillRegistry();
	this.viewContext = 'summary view';
	this.activeJob = null;

	this.results = {
		resultCount: 0,
		results: [],
		skills: [],
		processingTime: 0.0
	};
}

// This should only be called by the session
DiceContext.prototype.addJob = function (job) {
	this.results.results.push(job);
	this.results.resultCount++;
}
var DicejobsApp = function () {
	this.getPageDimensions();
	this.diceSession = new DiceSession();

	window.onresize = bind(this.getPageDimensions, this);
	this.searchState = {
		radius: (16.09344 * 5)	// 50 mi
	};
}

DicejobsApp.prototype.init = function (parentId, centroid, loc) {
	this.centroid = centroid;
	this.location = loc;

	if (loc) {
		this.searchState.where = loc;
		this.searchState.latlon = centroid.latitude + "," + centroid.longitude;
	}

	var parent = document.getElementById(parentId);
	this.paint(parent);

	var agent = new SearchAgent(this.diceSession, this.searchResultsPanel);
	agent.search(this.searchState);
}

DicejobsApp.info = {};

DicejobsApp.prototype.paint = function (parent) {
	var mm = new MainMenu(this.diceSession);
	mm.paint (parent);
	
	this.skillsPanel = new SkillsPanel();
	this.skillsPanel.setRegistry (this.diceSession.getSearchContext().registry);
	connect (this.diceSession.getSearchContext().registry, "refresh", this, 'updateSearchState');
	this.mapPanel = new MapPanel('100%', '300px', this.centroid, this.location, this.diceSession);
	connect (this.mapPanel, "location", this, 'updateSearchState');

	this.companyPanel = new CompanyPanel ();

	var infoBar = DIV({"class":"infoBar"});

	this.leftSideBar = DIV({style:"display:none;"}, this.companyPanel.paint());
	this.rightSideBar = DIV({id:"sidebar", "class":"colored-sidebar"}, this.skillsPanel.paint(), this.mapPanel.paint());

	this.searchResultsPanel = new SearchResultsPanel(this.diceSession, this.mapPanel, this.skillsPanel, this.companyPanel, this.leftSideBar, this.rightSideBar, infoBar);
	connect (this.searchResultsPanel, "sort", this, 'updateSearchState');

	this.contents = DIV({id:"contents", style:"min-height: "+(this.winHeight-210)+"px;"}, this.leftSideBar, this.searchResultsPanel.paint(), this.rightSideBar);
	parent.appendChild (DIV({id:"header2-menu-follow"}, infoBar, this.contents));
	//this.contents.onresize = bind(this.getPageDimensions, this);
	DicejobsApp.info.contentsDiv = this.contents;
}

DicejobsApp.prototype.setKeywordsField = function (keywordField) {
	this.keywordField = keywordField;
	this.keywordField.onkeypress = bind(this.checkSearchEntry, this);
}

DicejobsApp.prototype.setKeywordsSubmit = function (button) {
	button.onclick = bind(this.doSearch, this);
}

DicejobsApp.prototype.updateSearchState = function (doSearch, key, value) {
	this.searchState[key] = value;

	if (doSearch == true) {
		var agent = new SearchAgent(this.diceSession, this.searchResultsPanel);
		agent.search(this.searchState);
	}
}

DicejobsApp.prototype.doSearch = function () {
	if (this.keywordField.value == '') {
		alert ("Please enter keywords");
		return;
	}

	this.searchState.keywords = this.keywordField.value;

	// At some point, we want to disable the text box(es)
	var agent = new SearchAgent(this.diceSession, this.searchResultsPanel);
	agent.search(this.searchState);
}

DicejobsApp.prototype.checkSearchEntry = function (e) {
	var keyCode = (window.event) ? event.keyCode : e.keyCode;
	if (keyCode == 13) {
		this.doSearch();
	}
}

DicejobsApp.prototype.doWelcome = function () {
	var welcomePopup = new WelcomePanelPopup(this.mapPanel);
	welcomePopup.open();
}


DicejobsApp.prototype.getPageDimensions = function () {
	var d=document;
	if (typeof window.innerWidth!='undefined') {
		this.winWidth = window.innerWidth;
		this.winHeight = window.innerHeight;
	} else if ( d.documentElement && typeof d.documentElement.clientWidth!='undefined' && d.documentElement.clientWidth!=0 ) {
		this.winWidth = d.documentElement.clientWidth;
		this.winHeight = d.documentElement.clientHeight;
	} else if ( d.body && typeof d.body.clientWidth!='undefined') {
		this.winWidth = d.body.clientWidth;
		this.winHeight = d.body.clientHeight;
	}

	DicejobsApp.info = {
		winWidth: this.winWidth,
		winHeight: this.winHeight
	};

	DicejobsApp.windowWidth = this.winWidth;
	DicejobsApp.windowHeight = this.winHeight;
}
var DiceSession = function () {
	this.savedJobs = [];
	this.searchResults = {};
	this.savedContext = new DiceContext('saved');
	this.searchContext = new DiceContext('search');
	
	this.currentContext = this.searchContext;

	this.viewContext = 'summary view';
	this.context = 'search';
}

DiceSession.prototype.getCurrentContext = function () {
	return this.currentContext;
}

DiceSession.prototype.setContext = function (context) {
	this.context = context;
	signal (this, "context", context);
}

DiceSession.prototype.jobSaved = function (job) {
	var found = false;
	var savedJobs = this.savedContext.results.results;
	for (var i=0; i < savedJobs.length; i++) {
		if (savedJobs[i].id == job.id) {
			found = true;
			break;
		}
	}
	return found;
}

DiceSession.prototype.saveJob = function (job) {
	
	if (!this.jobSaved (job)) {
		this.savedContext.results.results.push(job);
		this.savedContext.results.resultCount++;
		signal (this, "jobCount", this.savedContext.results.resultCount);
	}
}

DiceSession.prototype.deleteJob = function (job) {
	var index = -1;
	for (var i=0; i < this.savedContext.results.results.length; i++) {
		if (this.savedContext.results.results[i].id == job.id) {
			index = i;
			break;
		}
	}
	if (index >= 0) {
		var j = this.savedContext.results.results.splice (index, 1);
		this.savedContext.results.resultCount--;
	}
	signal (this, "jobCount", this.savedContext.results.resultCount);
}

DiceSession.prototype.getSearchContext = function () {
	return this.searchContext;
}

DiceSession.prototype.getSavedContext = function () {
	return this.savedContext;
}

DiceSession.prototype.setSearchResults = function (results) {
	this.searchContext.results = results;
}
Function.prototype.inheritsFrom = function( BaseClassOrObject ){
    var instance = new BaseClassOrObject(this.PrototypeMarker);
    this.prototype = instance;
    return this;
};
var MainMenu = function (diceSession) {
	this.diceSession = diceSession;
	connect (this.diceSession, "jobCount", this, 'updateSaveTab');
	connect (this.diceSession, "updateMenuViewContext", this, 'setViewContext');
}

MainMenu.prototype.paint = function (parent) {
	this.results = A({href:"javascript:void(0);", 'class':'current'}, "Search Results");
	this.results.onclick = bind(this.changeContext, this);
	this.saved = A({href:"javascript:void(0);","class":"inactive"}, "Saved Results (0)");
	this.saved.onclick = bind(this.changeContext, this);
	this.comparisons = A({href:"javascript:void(0);","class":"inactive"}, "Comparisons");
	this.comparisons.onclick = bind(this.changeContext, this);

	this.summaryView = A({"class":"active", href:"javascript:void(0);"}, "summary view");
	this.summaryView.onclick = bind(this.switchViewContext, this);
	this.mapView = A({href:"javascript:void(0);"}, "map view");
	this.mapView.onclick = bind(this.switchViewContext, this);
	this.companyView = A({href:"javascript:void(0);"}, "company view");
	this.companyView.onclick = bind(this.switchViewContext, this);
	this.activeViewButton = this.summaryView;
	
	this.submenu = UL({id:"secondary"}, LI(null, this.summaryView), LI(null, this.companyView), LI(null,this.mapView));

	//var list = UL({id:"primary"}, LI(null, this.results, this.submenu), LI(null, this.saved), LI(null,this.comparisons));
	var list = UL({id:"primary"}, LI(null, this.results, this.submenu), LI(null, this.saved));

	var div = DIV({id:"header2-menu"}, list);
	parent.appendChild (div);
	parent.appendChild (DIV({id:"header2-sub-menu"}));
}

MainMenu.prototype.changeContext = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}
	if (txt == 'Search Results') {
		this.setStyle (this.results, "current");
		this.setStyle (this.saved, "inactive");
		this.setStyle (this.comparisons, "inactive");
		this.diceSession.setContext ("search");
	} else if (txt == "Comparisons") {
		this.setStyle (this.results, "inactive");
		this.setStyle (this.saved, "inactive");
		this.setStyle (this.comparisons, "current");
		this.diceSession.setContext ("compare");
	} else {
		this.setStyle (this.results, "inactive");
		this.setStyle (this.saved, "current");
		this.setStyle (this.comparisons, "inactive");
		this.diceSession.setContext ("save");
	}
}

MainMenu.prototype.setStyle = function (node, className) {
	node.setAttribute("class",className);
	node.setAttribute('className',className);
}

MainMenu.prototype.updateSaveTab = function (saveCount) {
	if (window.event) {
		this.saved.firstChild.nodeValue = "Saved Results (" + saveCount + ")";
	} else {
		this.saved.textContent = "Saved Results (" + saveCount + ")";
	}
}

MainMenu.prototype.switchViewContext = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}
	this.activeViewButton.setAttribute ("class", "default");
	this.activeViewButton.setAttribute ("className", "default");
	target.setAttribute ("class", "active");
	target.setAttribute ("className", "active");
	this.activeViewButton = target;

	signal (this.diceSession, "viewContext", txt);
}

MainMenu.prototype.setViewContext = function (viewContext) {
	this.activeViewButton.setAttribute ("class", "default");
	this.activeViewButton.setAttribute ("className", "default");

	if (viewContext == 'summary view') {
		this.summaryView.setAttribute ("class", "active");
		this.summaryView.setAttribute ("className", "active");

		this.activeViewButton = this.summaryView;
	} else if (viewContext == 'map view') {
		this.mapView.setAttribute ("class", "active");
		this.mapView.setAttribute ("className", "active");

		this.activeViewButton = this.mapView;
	} else {
		this.companyView.setAttribute ("class", "active");
		this.companyView.setAttribute ("className", "active");

		this.activeViewButton = this.companyView;
	}
}
var MapPanel = function (width, height, centroid, loc, diceSession) {
	this.height = height;
	this.width = width;
	
	this.centroid = centroid;
	this.location = loc;
	this.locationChanged = false;
	this.homeMarker = null;

	this.activeJob = null;

	this.diceSession = diceSession;

	this.jobs = [];
}


MapPanel.prototype.paint = function () {
	this.mapDiv = DIV({style:"width:"+this.width+";height:"+this.height+";margin-right: 6px; border: 1px #AAAAAA solid;"});

	this.radius = SELECT({style:"width:30%;"},
		OPTION({style:"color: #CC0000; font-weight: bold;", value:16.09344}, "10 miles"),
		OPTION({value:40.23360}, "25 miles"),
		OPTION({value:80.46720, selected:'true'}, "50 miles"),
		OPTION({value:160.9344}, "100 miles"),
		OPTION({value:0.0}, "Anywhere"));


	this.locationInput = INPUT({type:"TEXT", "class":"locationSearch", value:this.location});
	this.locationInput.onkeypress = bind(this.checkLocationEntry, this);
	var btn = INPUT({type:"BUTTON", "class":"btn searchBtn", value:"Change"});
	btn.onclick = bind(this.updateMapLocation, this);
	var controls = DIV({style:"margin-top: 2px;width:100%;"}, this.radius, this.locationInput, btn);

	this.container = DIV({"class":"mapElement"}, this.mapDiv, controls);
	setTimeout (bind(this.renderMap, this), 100);

	return this.container;
}

MapPanel.prototype.renderMap = function () {
	//alert ("Parent Dimensions: " + parent.style.width + " x " + parent.style.height);

	this.map = new GMap2(this.mapDiv);
	
	this.map.addMapType(G_SATELLITE_3D_MAP);
	this.map.addControl(new GLargeMapControl());
	this.map.addControl(new GMapTypeControl());
	this.map.enableDoubleClickZoom();
	this.map.enableScrollWheelZoom();
	
	GEvent.addListener (this.map, 'click', bind(this.viewJobDetails, this));

	this.setCenter(this.centroid.latitude, this.centroid.longitude, 13);
	this.setCentroid(this.centroid.latitude, this.centroid.longitude);
}

MapPanel.prototype.locationChanged = function () {
	return this.locationChanged;
}

MapPanel.prototype.checkLocationEntry = function (e) {
	var keyCode = (window.event) ? event.keyCode : e.keyCode;
	if (keyCode == 13) {
		this.updateMapLocation();
	}
}

MapPanel.prototype.setCenter = function (latitude, longitude, zoomlevel) {
	this.map.setCenter(new GLatLng(latitude, longitude), zoomlevel);
}

MapPanel.prototype.updateMapLocation = function () {
	if (this.locationInput.value == '') {
		alert("Please enter a city, zip, or state");
		return;
	}
	var geocoder = new GClientGeocoder();
	geocoder.getLatLng(this.locationInput.value, bind(this.setNewLocation, this));
	// This is where we update the map
}

MapPanel.prototype.setNewLocation = function (point) {
	if (point) {
		this.locationChanged = true;
		this.centroid.latitude = point.lat();
		this.centroid.longitude = point.lng();
		this.setCentroid (point.lat(), point.lng());
		this.setCenter (point.lat(), point.lng());

		this.location = this.locationInput.value;

		signal (this, "location", false, "radius", this.radius.options[this.radius.selectedIndex].value);
		signal (this, "location", false, "latlon", point.lat() + "," + point.lng());
		signal (this, "location", true, "where", this.locationInput.value);
	} else {
		alert ("Unable to locate '" + this.locationInput.value + "'. Please try again.");
	}
}

MapPanel.prototype.setCentroid = function (latitude, longitude) {
	if (this.homeMarker == null) {
		var blueIcon = new GIcon(G_DEFAULT_ICON);
		blueIcon.image = "http://dice.yerot.com/images/blue-marker.png";
		markerOptions = { icon:blueIcon };
		
		this.homeMarker = new GMarker(new GLatLng(latitude, longitude), markerOptions);
		this.map.addOverlay (this.homeMarker);
	} else {
		this.homeMarker.setLatLng(new GLatLng(latitude, longitude));
	}

}

MapPanel.prototype.addJob = function (job) {
	if (job.marker == null) {
		if (job.latitude != null && job.longitude != null) {
			var icon = new GIcon(G_DEFAULT_ICON);
			icon.image = "http://dice.yerot.com/images/"+job.idx+"-marker.png";
			markerOptions = {icon: icon};
			job.marker = new GMarker(new GLatLng(job.latitude, job.longitude), markerOptions);
			job.marker.job = job;
			this.map.addOverlay(job.marker);

			this.jobs.push (job);
		}
	}
}

MapPanel.prototype.resetJobs = function () {
	this.jobs = []
}

MapPanel.prototype.updateMapBounds = function () {
	var bounds = this.map.getBounds();

	for (var i=0; i < this.jobs.length; i++) {
		if (this.jobs[i].marker != null) {
			bounds.extend (this.jobs[i].marker.getLatLng());
		}
	}

	this.map.setCenter (bounds.getCenter(), this.map.getBoundsZoomLevel(bounds));

}

MapPanel.prototype.removeJob = function (job) {
	if (job.marker != null) {
		this.map.removeOverlay (job.marker);
		job.marker = null;
	}
}

MapPanel.prototype.activateJob = function (job) {
	if (job.marker !=  null) {
		this.activeJob = job;
		// TODO: Show help balloon at some point, too
		this.map.setCenter (new GLatLng(job.latitude, job.longitude));
		if (job.viewMode == 'brief')
			job.marker.openInfoWindow (this.getDetailedJobInfo(job));
		else
			job.marker.openInfoWindow (this.getJobInfo(job));
	}
}

MapPanel.prototype.deactivateJob = function (job) {
	if (job.marker != null) {
		this.activeJob = null;
		job.marker.closeInfoWindow ();
	}
}

MapPanel.prototype.getJobInfo = function (job, w) {
	var jobLink = A({href:"javascript:void(0);", style:"color: #cc0000; text-decoration: underline; font-weight: bold;"}, job.title);
	var companyLink = A({href:"javascript:void(0);", style:"color: #022383; text-decoration: none;"}, job.companyName);
	var loc = DIV({}, "location: " + job.location);
	var info = DIV(null, DIV(null, jobLink), DIV(null, "company: ", companyLink), loc);

	return info;
}

MapPanel.prototype.getDetailedJobInfo = function (job, w) {
	var jobLink = A({href:"javascript:void(0);", style:"color: #cc0000; text-decoration: underline; font-weight: bold;"}, job.title);
	var companyLink = A({href:"javascript:void(0);", style:"color: #022383; text-decoration: none;"}, job.companyName);
	var loc = DIV({}, "location: " + job.location);
	var moreLink = A({href:"javascript:void(0);"}, "more");
	moreLink.onclick = bind(this.showJobDetails, this);
	moreLink.job = job;
	var div = DIV();
	div.innerHTML = job.htmlDescription;
	var width = this.mapDiv.clientWidth - 100;
	var height = this.mapDiv.clientHeight - 150;
	this.summaryDiv = DIV({style:"border-bottom: 1px solid black; border-top: 1px solid black; margin-top: 4px;margin-bottom: 4px;padding-bottom: 4px; overflow-y: auto; overflow-x: none; max-height:"+(height-100)+"px;padding-right:4px; padding-top:5px;"}, div);

	var apply1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Apply");
	var apply2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Apply");

	var action1;
	var action2;
	if (this.diceSession.getCurrentContext() == 'saved') {
		action1 = A({"class":"notesMenu", href:"javascript:void(0);"}, 'Delete');
		action1.job = job;
		//action1.onclick = bind(this.deleteJob, this);
		action2 = A({"class":"notesMenu", href:"javascript:void(0);"}, 'Delete');
		action2.job = job;
		//action2.onclick = bind(this.deleteJob, this);
		action1.linkButton = action2;
		action2.linkButton = action1;
	} else {
		var saveText = (this.diceSession.jobSaved(job) ? "Saved" : "Save");
		action1 = A({"class":"notesMenu", href:"javascript:void(0);"}, saveText);
		action1.onclick = bind (this.saveJob, this);
		action1.job = job;
		action2 = A({"class":"notesMenu", href:"javascript:void(0);"}, saveText);
		action2.onclick = bind (this.saveJob, this);
		action2.job = job;
		action1.linkButton = action2;
		action2.linkButton = action1;
	}
	var email1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Email");
	var email2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Email");

	var close1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Close");
	close1.job = job;
	//close1.onclick = bind(this.hideJobDetails, this);
	var close2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Close");
	close2.job = job;
	//close2.onclick = bind(this.hideJobDetails, this);

	var topMenu = DIV({style:"padding-bottom: 3px; position: relative;"}, apply1, action1, email1); 
	var bottomMenu = DIV({style:"padding-top: 3px; position: relative; height: 1.5em;"}, apply2, action2, email2);

	var info = DIV({style:"width:" + (width-30) + "px; height:"+height+"px;padding-right: 5px;"}, 
			topMenu,
			DIV({style:"clear:both;"}, jobLink), DIV(null, "company: ", companyLink), this.summaryDiv, loc, bottomMenu);

	return info;
}

MapPanel.prototype.viewJobDetails = function (overlay) {
	if (overlay != null) {
		if (overlay.job) {
			var job = overlay.job;

			signal (this, 'highlight', job); // Highlight the job
			this.activateJob (job);
		}
	}
}

MapPanel.prototype.showJobDetails = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	job = target.job;

	while (this.summaryDiv.firstChild != null)
		this.summaryDiv.removeChild (this.summaryDiv.firstChild);

	var div = DIV();
	div.innerHTML = job.htmlDescription;
	this.summaryDiv.appendChild (div);
}

MapPanel.prototype.saveJob = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
		target.textContent = "Saved";
		if (target.linkButton)
			target.linkButton.textContent = "Saved";
	} else {
		target = window.event.srcElement;
		target.firstChild.nodeValue = "Saved";
		if (target.linkButton)
			target.linkButton.firstChild.nodeValue = "Saved";
	}

	//job = target.job;
	this.diceSession.saveJob (this.activeJob);
}

MapPanel.prototype.fade = function () {
	fade (this.container);
}

MapPanel.prototype.appear = function (postFunc) {
	if (postFunc)
		appear (this.container, {afterFinish: postFunc});
	else
		appear (this.container);
}

MapPanel.prototype.expandMapToHeight = function (targetHeight) {
	var currentHeight = this.mapDiv.clientHeight;

	var percent = targetHeight / currentHeight * 100.0;

	//alert ("Scaling to percentage: " +percent+"%");

	Scale (this.mapDiv, percent, {scaleX: false, scaleContent: false, afterFinish: bind(this.updateMapSize, this)});
}

MapPanel.prototype.expandMapToWidth = function (targetWidth) {
	var currentWidth = this.mapDiv.clientWidth;

	var percent = targetWidth / currentWidth * 100.0;

	//alert ("Scaling to percentage: " +percent+"%");

	Scale (this.mapDiv, percent, {scaleY: false, scaleContent: false, afterFinish: bind(this.updateMapSize, this)});
}

MapPanel.prototype.updateMapSize = function () {
	if (!this.mapDiv) return;
	this.mapDiv.style.width  = this.mapDiv.clientWidth + "px";
	this.mapDiv.style.height = this.mapDiv.clientHeight + "px";
	this.map.checkResize();
	if (this.activeJob != null)
		this.activateJob (this.activeJob);
}

MapPanel.prototype.setExpandableWidth = function () {
	this.mapDiv.style.width = '100%';
}
var Panel = function (title, width, height) {
	this.title = title;
	this.height = height;
	this.width = width;
}

Panel.prototype.paint = function () { 
	var titleBar = DIV({"class":"panelTitleBar"}, this.title);

	this.content = DIV({"class":"panelContent", "style":"width:"+this.width+";height:"+this.height+";"});
	this.createControl(this.content);

	var panel = DIV({"class":"panel"}, titleBar, this.content);
	
	return panel;
}

// Used with the PanelPopup class
Panel.prototype.getContainer = function () {
	return this.container;
}
var SearchAgent = function (diceSession, searchResultsPanel) {
	this.diceSession = diceSession;
	this.searchResultsPanel = searchResultsPanel;
}

SearchAgent.prototype.search = function (searchState) {
	//alert ("searchState:\nKeywords: " + searchState.keywords +"\nWhere: " + searchState.where +"\nRadius: " + searchState.radius);
	this.searchResultsPanel.searching();
	var d = loadJSONDoc("http://dice.yerot.com/jobs/", searchState);
	d.addCallbacks (bind(this.resultsCallback,this), bind(this.errorCallback,this));
}

// Used with the SearchAgentPopup class
SearchAgent.prototype.resultsCallback = function (results) {
	this.diceSession.setSearchResults (results);
	this.searchResultsPanel.setSearchResults(results);
}

SearchAgent.prototype.errorCallback = function (error) {
	alert(error);
}
var SearchResultsPanel = function (diceSession, mapPanel, skillsPanel, companyPanel, leftSidebar, rightSidebar, infoPanel) {
	this.leftSidebar = leftSidebar;
	this.rightSidebar = rightSidebar;
	this.diceSession = diceSession;
	this.currentPage = 1;
	this.totalPages = 1;
	this.pageSize = 5;
	this.sortMethod = 'relevance';
	this.mapPanel = mapPanel;
	this.skillsPanel = skillsPanel;
	this.companyPanel = companyPanel;
	this.infoPanel = infoPanel;
	this.index = 0;
	this.processingTime = 0.0;
	this.showSummary = true;
	this.renderCount = 0;
	this.renderTotal = 0;

	this.activeJob = null;

	this.ordered = false;
	this.orderedIndex = 0;

	this.searchingImage = new Image();
	this.searchingImage.src = "images/loading.gif";

	this.context = this.diceSession.getCurrentContext();

	this.skillRegistry = this.context.registry;

	connect (this.diceSession, "context", this, 'switchContext');
	connect (this.diceSession, "viewContext", this, 'switchViewContext');
	connect (this.companyPanel, "viewResults", this, 'setSearchResults');
	connect (this.mapPanel, 'highlight', this, 'doHighlightJob');
	connect (this, "rendered", this, "updateMap");
}


SearchResultsPanel.prototype.paint = function () {
	
	this.topPrevious = A({"class":"disabled", href:"javascript:void(0);"}, "previous");
	this.topPrevious.onclick = bind(this.previousPage, this);
	this.topNext = A({"class":"disabled", href:"javascript:void(0);"}, "next");
	this.topNext.onclick = bind(this.nextPage, this);
	this.topPageNumber = SPAN({"class":"pagenumer"}, " page 1 of 1");

	this.bottomPrevious = A({"class":"disabled", href:"javascript:void(0);"}, "previous");
	this.bottomPrevious.onclick = bind(this.previousPage, this);
	this.bottomNext = A({"class":"disabled", href:"javascript:void(0);"}, "next");
	this.bottomNext.onclick = bind(this.nextPage, this);
	this.bottomPageNumber = SPAN({"class":"pagenumer"}, " page 1 of 1");

	var sortDate = A({id:"dateLink", href:"javascript:void(0);"}, "date");
	sortDate.onclick = bind(this.setSortMethod, this);
	var sortDistance = A({id:"distanceLink", href:"javascript:void(0);"}, "distance");
	sortDistance.onclick = bind(this.setSortMethod, this);
	var sortRelevance = A({id:"relevanceLink", "class":"active", href:"javascript:void(0);"}, "relevance");
	sortRelevance.onclick = bind(this.setSortMethod, this);
	var sortCompany = A({id:"companyLink", href:"javascript:void(0);"}, "company");
	sortCompany.onclick = bind(this.setSortMethod, this);
	this.activeSortControl = sortRelevance;
	
	this.relevanceSpan = SPAN({style:"display:inline;"}, sortRelevance, " | ");

	this.sortControls = DIV({"class":"pageActionCtrl"}, "sort by: ", this.relevanceSpan, sortDate, " | ", sortDistance, " | ", sortCompany);

	this.topPager = DIV({"class":"pager"}, 
		P(null, " "+unescape("%AB")+" ", this.topPrevious, " | ", this.topNext, " "+unescape("%BB")+" ", this.topPageNumber), this.sortControls);
	this.jobPosts = UL({"class":"posts"});
	this.bottomPager = DIV({"class":"pager"}, 
		P(null, " "+unescape("%AB")+" ", this.bottomPrevious, " | ", this.bottomNext, " "+unescape("%BB")+" ", this.bottomPageNumber));

	var show5 = A({"class":"active", href:"javascript:void(0);"}, "5");
	show5.onclick = bind(this.changePageSize, this);
	this.activePageSizeControl = show5;
	var show10 = A({href:"javascript:void(0);"}, "10");
	show10.onclick = bind(this.changePageSize, this);
	var show15 = A({href:"javascript:void(0);"}, "15");
	show15.onclick = bind(this.changePageSize, this);
	var show30 = A({href:"javascript:void(0);"}, "30");
	show30.onclick = bind(this.changePageSize, this);
	var viewConfig = DIV({"class":"viewconfig"}, "show ", show5, " ", show10, " ", show15, " ", show30, " items per page");

	//this.infoPanel = DIV({"class":"viewconfig"});
	//alert ("eh: " + DicejobsApp.windowHeight);
	//this.jobsContainer = DIV({style:"background: #ff00ff; overflow:auto; width:300; height:"+(DicejobsApp.windowHeight-275)+";"}, this.jobPosts);
	var height = DicejobsApp.info.winHeight - 190;
	//this.jobsContainer = DIV({style:"margin: auto; overflow-x: none; overflow-y:auto; max-height: "+(height-85)+"px; top:0;"}, this.jobPosts);
	this.jobsContainer = DIV({}, this.jobPosts);

	//this.content = DIV({style: "width:64%;height: "+height+"px;"}, this.infoPanel, this.topPager, this.jobsContainer, this.bottomPager, viewConfig);
	this.content = DIV({style: "min-height: " + height+ "px;width:64%;"}, this.topPager, this.jobsContainer, this.bottomPager, viewConfig);

	return this.content;
}

SearchResultsPanel.prototype.searching = function () {
	this.clearResults();
	var div = DIV({style:"margin:auto;width:100%;text-align:center;"}, this.searchingImage, DIV({style: "padding-top: 50px;"},"S E A R C H I N G..."));
	this.jobPosts.appendChild (LI(null, div));
	//appear(div, {duration: 2.0} );
}

SearchResultsPanel.prototype.setSearchResults = function (results) {
	this.currentPage = 1;
	this.results = results;
	this.skillRegistry.clearRegisteredJobTags();
	this.skillsPanel.removeSkills();
	this.processingTime = results.processingTime;
	this.totalPages = (results.results.length % this.pageSize > 0) ? Math.floor(results.results.length / this.pageSize) + 1: results.results.length / this.pageSize;

/*
	var skillSet = "";
	if (this.results.skills.length > 0) {
		skillSet = this.results.skills[0];
		for (var i=1; i < this.results.skills.length; i++) {
			skillSet += ","+this.results.skills[i].skill;
		}
	} 

	this.results.skillSet = skillSet;
*/
	if (!this.results.stale) {
		this.companyPanel.setResults (this.results);
	}

	if (results.results.length > 0) {
		if (this.infoPanel.firstChild != null)
			this.infoPanel.removeChild (this.infoPanel.firstChild);

		var div = DIV();

		if (this.context.name == 'saved') {
			if (this.results.stale && this.companyPanel.getActiveCompanyName() != 'All Companies') {
				div.innerHTML = "showing <B><I>" + results.resultCount + "</I></B> saved jobs posted by <B>" + this.companyPanel.getActiveCompanyName() + "</B>";
			} else {
				div.innerHTML = "showing <B><I>" + results.resultCount + "</I></B> saved jobs";
			}
		} else {
			if (this.results.stale && this.companyPanel.getActiveCompanyName() != 'All Companies') {
				div.innerHTML = "showing <B><I>" + results.resultCount + "</I></B> jobs posted by <B>" + this.companyPanel.getActiveCompanyName() + "</B>";
			} else {
				div.innerHTML = "found <B><I>" + results.resultCount + "</I></B> jobs in the <B>" + this.mapPanel.location + "</B> area";
			}
		} 
		this.infoPanel.appendChild (div);

		this.renderPage();
		this.skillsPanel.setSkills(results.skills);
	} else {
		this.clearResults();
		if (this.infoPanel.firstChild != null)
			this.infoPanel.removeChild (this.infoPanel.firstChild);
		if (this.context.name == 'saved') {
			this.infoPanel.appendChild (DIV(null, "no saved jobs" ));
		} else {
			this.infoPanel.appendChild (DIV(null, "found no results in your area" ));
		}
	}
}

/**
 * Beautify this at somepoint */
SearchResultsPanel.prototype.clearResults = function () {
	while (this.jobPosts.firstChild != null) {
		if (this.jobPosts.firstChild.job != null)
			this.mapPanel.removeJob (this.jobPosts.firstChild.job);
		this.jobPosts.removeChild (this.jobPosts.firstChild);
	}

	this.mapPanel.resetJobs();
	this.topPager.style.visibility = 'hidden';
	this.bottomPager.style.visibility = 'hidden';
	this.index = 0;
}

SearchResultsPanel.prototype.renderPage = function () {
	if (this.results == null || this.results.results.length == 0) return;
	this.clearResults();
	var offset = (this.pageSize * (this.currentPage-1));
	var terminator = Math.min(offset+this.pageSize, this.results.results.length);
	var renderedOffset = 0;

	this.renderCount = 0;
	this.renderTotal = terminator - offset;
	//alert (this.renderCount + " <> " + this.renderTotal);

	if (this.sortMethod == 'distance') {
		this.fetchTotal = 0;
		this.fetchCount = 0;
		if (this.context.name == 'saved') {
			for (var i=offset; i < terminator; i++) {
				this.jobPosts.appendChild (this.renderJob(this.results.results[i]));
				this.mapPanel.addJob (this.results.results[i]);
				signal (this, "rendered");
			}
		} else {
			// First, find out how many we have to render
			for (var i=offset; i < terminator; i++) {
				if (!this.results.results[i].full)
					this.fetchTotal++;
			}
			for (var i=offset; i < terminator; i++) {
				if (!this.results.results[i].full)
					this.fetchFullRecord (this.results.results[i]);
			}
		}
	} else {
		if (this.ordered) {
			this.orderedIndex = offset;
			this.orderedIndexTerminator = terminator;
		}

		for (var i=offset; i < terminator; i++) {
			if (this.results.results[i].full != null) {
				this.jobPosts.appendChild (this.renderJob(this.results.results[i]));
				this.mapPanel.addJob (this.results.results[i]);
				renderedOffset++;
				signal (this, "rendered");
			} else {
				if (this.ordered) {
					if (offset + renderedOffset > this.orderedOffset)
						this.orderedOffset = offset + renderedOffset;
				}
				this.fetchFullRecord (this.results.results[i]);
			}
		}
	}

	this.topPageNumber.removeChild(this.topPageNumber.firstChild);
	this.topPageNumber.appendChild(document.createTextNode(" page " + this.currentPage + " of " + this.totalPages));

	this.bottomPageNumber.removeChild(this.bottomPageNumber.firstChild);
	this.bottomPageNumber.appendChild(document.createTextNode(" page " + this.currentPage + " of " + this.totalPages));

	this.topPager.style.visibility = 'visible';
	this.bottomPager.style.visibility = 'visible';
	this.updatePagerControls();
}

SearchResultsPanel.prototype.updateMap = function () {
	//alert (this.renderCount + " <> " + this.renderTotal);
	if (++this.renderCount == this.renderTotal) {
		this.mapPanel.updateMapBounds ();
	}
}

SearchResultsPanel.prototype.fetchFullRecord = function (job) {
	//var d = loadJSONDoc("http://dice.yerot.com/jobs/", {id: job.id, ss: this.results.skillSet});
	var d = loadJSONDoc("http://dice.yerot.com/jobs/", {id: job.id});
	d.addCallbacks (bind(this.updateJobCallback, this), bind(this.errorCallback,this));
}

SearchResultsPanel.prototype.updateJobCallback = function (result) {
	var processingTime = result.processingTime;	// At some point, we need to tally up the processing times
	this.processingTime += processingTime;
	var job = result.job;
	for (var i=0; i < this.results.results.length; i++) {
		if (this.results.results[i].id == job.id) {
			this.results.results[i].full = true;
			this.results.results[i].skills = job.skills; // Since this is where sills are parsed
			this.results.results[i].htmlDescription = job.htmlDescription; // Since this is where sills are parsed
			if (job.date != '') this.results.results[i].date = job.date;
			if (job.timestamp != '') this.results.results[i].timestamp = job.timestamp;
			if (job.description != '') this.results.results[i].description = job.description;
			if (job.companyLink != '') this.results.results[i].companyLink = job.companyLink;
			if (job.companyLogo != '') this.results.results[i].companyLogo = job.companyLogo;
			if (job.skillSet != '') this.results.results[i].skillSet = job.skillSet; 
			job = this.results.results[i];
			if (this.ordered) {
				// Guarantee the order of rendering!
				// NOTE: this assumes that all results come
				// back properly
				if (this.sortMethod == 'distance') {
					if (++this.fetchCount >= this.fetchTotal) {
						var offset = (this.pageSize * (this.currentPage-1));
						var terminator = Math.min(offset+this.pageSize, this.results.results.length);
						for (var i=offset; i < terminator; i++) {
							this.jobPosts.appendChild (this.renderJob(this.results.results[i]));
							this.mapPanel.addJob (this.results.results[i]);
							signal (this, "rendered");
						}
					} 
				} else if (i == this.orderedIndex) {
					var done = false;
					while (!done) {
						var jobDom = this.renderJob(this.results.results[this.orderedIndex]);
						this.jobPosts.appendChild (jobDom);
						this.mapPanel.addJob (this.results.results[this.orderedIndex]);
						signal (this, "rendered");

						this.orderedIndex++;
						if (this.orderedIndex >= this.results.results.length || !this.results.results[this.orderedIndex].full)
							done = true;
					}
				}
			} else {
				var jobDom = this.renderJob(job);
				this.jobPosts.appendChild (jobDom);
				//appear(jobDom);
				this.mapPanel.addJob (job);
				signal (this, "rendered");
			}
			//alert ("JOB: " + job.id + " => " + job.title + " => " + job.companyLogo);
			break;
		}
	}

}

SearchResultsPanel.prototype.errorCallback = function (error) {
        alert(error);
}


SearchResultsPanel.prototype.renderJob = function (job) {
	var title = A({href:"javascript:void(0);", "class":"bmark-title link-title", context:"job", link:job.link}, job.title);
	title.job = job;
	title.onclick = bind(this.highlightJob, this);
	var company = A({href:"javascript:void(0);", "class":"bmark-link web-link", context:"company", link:job.companyLink}, job.companyName);
	//company.onclick = bind(this.showCompany, this);
	
	var skills = DIV({"class":"info"}, "skills: ");
	if (job.skills.length > 0) {
		var a =  A({"class":"tag", href:"javascript:void(0);"}, job.skills[0].name);
		a.skill = job.skills[0];
		this.skillRegistry.registerSkill (a);
		skills.appendChild (a);

		for (var i=1; i < job.skills.length; i++) {
			var a = A({"class":"tag", href:"javascript:void(0);"}, job.skills[i].name);
			a.skill = job.skills[i];
			this.skillRegistry.registerSkill (a);
			var s = SPAN(null);
			s.innerHTML = " &nbsp;&middot;&nbsp; ";
			skills.appendChild (s);
			skills.appendChild (a);
		}
	} else {
		skills.appendChild (document.createTextNode("none"));
	}
	var titleInfo = DIV({"class":"post-link"}, "on " + job.date + " posted by ", company);
	var distance = this.getDistance (job);
	//var distance = ' (about 30 miles from you)';
	var link;
	var mapLink;
	if (job.latitude != null && job.longitude != null) {
		job.idx = ++this.index;
		link = "http://dice.yerot.com/images/"+job.idx+"-marker.jpg";
		var icon = IMG({border:0, src:link, job:job});
		icon.job = job;
		mapLink = A({href:"javascript:void(0);"}, icon);
		mapLink.onclick = bind(this.activeJobOnMap, this);
	} else {
		//job.idx = 0;
		var src = "http://dice.yerot.com/images/unmarked.jpg";
		mapLink = IMG({border:0, src:src});
	}

	var moreLink = A({href:"javascript:void(0);"}, "more");
	moreLink.onclick = bind(this.showJobDetails, this);
	moreLink.job = job;

	job.skillsDiv = skills;

	job.viewMode = 'summary';


	var details = A({"class":"notesMenu", href:"javascript:void(0);"}, "Details");
	details.job = job;
	details.onclick = bind(this.showJobDetails, this);
	var apply = A({"class":"notesMenu", href:"javascript:void(0);"}, "Apply");
	var saveText = (this.diceSession.jobSaved(job) ? "Saved" : "Save");
	var save = A({"class":"notesMenu", href:"javascript:void(0);"}, saveText);
	save.job = job;
	save.onclick = bind(this.saveJob, this);
	
	job.topMenuDiv = DIV({style:"height:1.5em; display:none;padding-bottom: 3px; position: relative;"}, 
			DIV({style:"top:0px; right:0px; position:absolute;"}, details, apply, save));


	job.detailsDiv = this.generateDetailDiv (job);
	job.summaryDiv = DIV({"class":"shrtNotes"}, job.description, " [ ", moreLink, " ]");
	job.descriptionDiv = DIV({"class":"notes"}, job.summaryDiv, job.detailsDiv);
	job.contentDiv = DIV({"class":"postContent"}, 
				job.topMenuDiv,
				DIV({"class":"post-container"}, 
					DIV({"class":"post-title"}, title, titleInfo)
				),
				job.descriptionDiv,
				DIV({"class":"meta"}, DIV({"class":"info"}, "location: ", job.location, distance)),
				DIV({"class":"meta"}, skills)
			);

	var posting = LI({"class":"post"}, 
		DIV({style:"width:100%;"}, 
			DIV({style:"width: 25px; float:left;display:inline;"}, mapLink),
			job.contentDiv
		)
	);

	if (!this.showSummary) {
		job.summaryDiv.setAttribute ('class', 'shrtNotes summarized');
		job.summaryDiv.setAttribute ('className', 'shrtNotes summarized');
		job.skillsDiv.setAttribute ('class', 'info summarized');
		job.skillsDiv.setAttribute ('className', 'info summarized');
		job.viewMode = 'brief';
	}

	posting.job = job;
	return posting;
}

SearchResultsPanel.prototype.nextPage = function () {
	if (this.currentPage < this.totalPages) {
		this.currentPage++;
		this.skillRegistry.clearRegisteredJobTags();
		this.renderPage();
	}
}

SearchResultsPanel.prototype.previousPage = function () {
	if (this.currentPage > 1) {
		this.currentPage--;
		this.skillRegistry.clearRegisteredJobTags();
		this.renderPage();
	}
}

SearchResultsPanel.prototype.changePageSize = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}

	this.activePageSizeControl.setAttribute("class", "default");
	this.activePageSizeControl.setAttribute("className", "default");
	target.setAttribute("class", "active");
	target.setAttribute("className", "active");
	this.activePageSizeControl = target;

	this.pageSize = txt;
	if (this.results == null) {
		this.totalPages = 1;
	} else {
		this.totalPages = (this.results.results.length % this.pageSize > 0) ? Math.floor(this.results.results.length / this.pageSize) + 1: this.results.results.length / this.pageSize;
	}
	this.currentPage = 1;	// Since we are changing page size, reset
	this.renderPage();

}

SearchResultsPanel.prototype.updatePagerControls = function () { 
	if (this.currentPage == 1) { 
		this.topPrevious.setAttribute("class", "disabled");
		this.topPrevious.setAttribute("className", "disabled");
		this.bottomPrevious.setAttribute("class", "disabled");
		this.bottomPrevious.setAttribute("className", "disabled"); 
	} else {
		this.topPrevious.setAttribute("class", "default");
		this.topPrevious.setAttribute("className", "default");
		this.bottomPrevious.setAttribute("class", "default");
		this.bottomPrevious.setAttribute("className", "default"); 
	}

	if (this.currentPage == this.totalPages) {
		this.topNext.setAttribute("class", "disabled");
		this.topNext.setAttribute("className", "disabled");
		this.bottomNext.setAttribute("class", "disabled");
		this.bottomNext.setAttribute("className", "disabled");
	} else {
		this.topNext.setAttribute("class", "default");
		this.topNext.setAttribute("className", "default");
		this.bottomNext.setAttribute("class", "default");
		this.bottomNext.setAttribute("className", "default");
	}
}

SearchResultsPanel.prototype.setSortMethod = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}

	this.activeSortControl.setAttribute("class", "default");
	this.activeSortControl.setAttribute("className", "default");
	target.setAttribute("class", "active");
	target.setAttribute("className", "active");
	this.activeSortControl = target;

	this.sortMethod = txt;

	this.doSort ();
}

SearchResultsPanel.prototype.doSort = function () {
	if (this.sortMethod == 'date') {
		if (this.context.name == 'saved') {
			this.searching();
			this.doDateSort ();
			this.setSearchResults (this.results);
		} else {
			this.ordered = true;
			signal (this, "sort", true, "sort", 7);
		}
	} else if (this.sortMethod == 'relevance') {
		// saved context should never get here
		this.ordered = false;
		signal (this, "sort", true, "sort", "");
	} else if (this.sortMethod == 'company') {
		if (this.context.name == 'saved') {
			this.searching();
			this.doCompanySort();
			this.setSearchResults (this.results);
		} else {
			this.ordered = true;
			signal (this, "sort", true, "sort", 1);
		}
	} else if (this.sortMethod == 'distance') {
		// This is where we do manual distance sorting!
		this.ordered = true;
		this.searching();
		this.doDistanceSort();
		this.setSearchResults (this.results);
	}
		
}

SearchResultsPanel.prototype.doDateSort = function () {
	var tmp;

	for (var i=0; i < this.results.results.length; i++) {
		for (var j=i; j < this.results.results.length; j++) {
			if (this.results.results[j].timestamp > this.results.results[i].timestamp) {
				tmp = this.results.results[i];
				this.results.results[i] = this.results.results[j];
				this.results.results[j] = tmp;
			}
		}
	}
}

SearchResultsPanel.prototype.doCompanySort = function () {
	var tmp;

	for (var i=0; i < this.results.results.length; i++) {
		for (var j=i; j < this.results.results.length; j++) {
			if (this.results.results[j].companyName < this.results.results[i].companyName) {
				tmp = this.results.results[i];
				this.results.results[i] = this.results.results[j];
				this.results.results[j] = tmp;
			}
		}
	}
}

SearchResultsPanel.prototype.doDistanceSort = function () {
	var tmp;

	// First make sure all jobs in cache have distances:
	for (var i=0; i < this.results.results.length; i++) {
		this.getDistance (this.results.results[i]);
	}

	for (var i=0; i < this.results.results.length; i++) {
		for (var j=i; j < this.results.results.length; j++) {
			if (this.results.results[j].distance < this.results.results[i].distance) {
				tmp = this.results.results[i];
				this.results.results[i] = this.results.results[j];
				this.results.results[j] = tmp;
			}
		}
	}
}

SearchResultsPanel.prototype.highlightJob = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	job = target.job;

	this.doHighlightJob (job);
}

SearchResultsPanel.prototype.doHighlightJob = function (job) {

	if (this.activeJob != null) {
		this.deactivateJob (this.activeJob);
		if (job.id == this.activeJob.id) {
			this.activeJob = null;
			return;
		}
	}

	this.activeJob = job;

	job.contentDiv.setAttribute ("class", "postContent postContentActive");
	job.contentDiv.setAttribute ("className", "postContent postContentActive");

	if (job.viewMode != 'brief')
		blindDown (job.topMenuDiv);

	// Show job on map as well
	this.mapPanel.activateJob (job);

	// Add buttons on panel to show details and Save/Saved
}

SearchResultsPanel.prototype.showJobDetails = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	job = target.job;

	if (this.activeJob == null || this.activeJob.id != job.id) {
		this.deactivateJob (this.activeJob);
		this.activeJob = job;
		this.mapPanel.activateJob (job);
		job.contentDiv.setAttribute ("class", "postContent postContentActive");
		job.contentDiv.setAttribute ("className", "postContent postContentActive");
	}

	blindUp (job.summaryDiv, {afterFinish: function () { blindDown(job.detailsDiv, {afterFinish: function () {ScrollTo(job.contentDiv) }}); }});
	//blindDown (job.detailsDiv);

	job.viewMode = 'details';
}

SearchResultsPanel.prototype.hideJobDetails = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	job = target.job;

	blindUp (job.detailsDiv, {afterFinish: function () { blindDown(job.summaryDiv);}});
	//blindDown (job.summaryDiv);

	job.viewMode = 'summary';
}

SearchResultsPanel.prototype.deactivateJob = function (job) {
	if (job == null) return;
	job.contentDiv.setAttribute ("class", "postContent");
	job.contentDiv.setAttribute ("className", "postContent");

	this.mapPanel.deactivateJob (job);

	if (job.viewMode != 'brief')
		blindUp (job.topMenuDiv);

	if (job.viewMode == 'details') {
		blindDown (job.summaryDiv);
		blindUp (job.detailsDiv);
		job.viewMode = 'summary';
	}
	
}

SearchResultsPanel.prototype.generateDetailDiv = function (job) {
	var apply1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Apply");
	var apply2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Apply");

	var action1;
	var action2;
	if (this.context.name == 'saved') {
		action1 = A({"class":"notesMenu", href:"javascript:void(0);"}, 'Delete');
		action1.job = job;
		action1.onclick = bind(this.deleteJob, this);
		action2 = A({"class":"notesMenu", href:"javascript:void(0);"}, 'Delete');
		action2.job = job;
		action2.onclick = bind(this.deleteJob, this);
		action1.linkButton = action2;
		action2.linkButton = action1;
	} else {
		var saveText = (this.diceSession.jobSaved(job) ? "Saved" : "Save");
		action1 = A({"class":"notesMenu", href:"javascript:void(0);"}, saveText);
		action1.job = job;
		action1.onclick = bind(this.saveJob, this);
		action2 = A({"class":"notesMenu", href:"javascript:void(0);"}, saveText);
		action2.job = job;
		action2.onclick = bind(this.saveJob, this);
		action1.linkButton = action2;
		action2.linkButton = action1;
	}
	var email1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Email");
	var email2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Email");

	var close1 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Close");
	close1.job = job;
	close1.onclick = bind(this.hideJobDetails, this);
	var close2 = A({"class":"notesMenu", href:"javascript:void(0);"}, "Close");
	close2.job = job;
	close2.onclick = bind(this.hideJobDetails, this);

	var topMenu = DIV({style:"padding-bottom: 3px; position: relative;"}, apply1, action1, email1, 
			DIV({style:"top:0px; right:0px; position:absolute;"}, close1));
	var bottomMenu = DIV({style:"padding-top: 3px; position: relative; height: 1.5em;"}, apply2, action2, email2, 
			DIV({style:"right:0px; position:absolute;"}, close2));

	var div = DIV({});
	div.innerHTML = job.htmlDescription;

	var height = DicejobsApp.info.winHeight - 250;
	var scroll = DIV({style:"clear: both; height:" + (height-40) + "px; max-height: " + (height-40) + "ps; width:100%; overflow-y: scroll; overflow-x: none;"}, div);

	var height = DicejobsApp.info.winHeight - 250;
	var style = "margin-left: auto; margin-right: auto; background-color: #FFFFFF; "
			+"border: 1px black dashed; padding: 5px; width: 95%; "
			+"height: " + height + "px; min-height: " + height + "px; max-height: " + height + "px; display: none;"

	//var contents = DIV({"class":"postDescription"}, topMenu, div, bottomMenu);
	//var contents = DIV({style:"margin-left: auto; margin-right: auto; background-color: #FFFFFF; border: 1px black dashed; padding: 5px; width: 95%; height: 500px; min-height: 500px; max-height: 500px; display: none;"}, topMenu, div, bottomMenu);
	var contents = DIV({style:style}, topMenu, scroll, bottomMenu);

	return contents;
}

SearchResultsPanel.prototype.saveJob = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
		target.textContent = "Saved";
		if (target.linkButton)
			target.linkButton.textContent = "Saved";
	} else {
		target = window.event.srcElement;
		target.firstChild.nodeValue = "Saved";
		if (target.linkButton)
			target.linkButton.firstChild.nodeValue = "Saved";
	}

	job = target.job;

	this.diceSession.saveJob(job);
}

SearchResultsPanel.prototype.deleteJob = function (e) {
	var target;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	job = target.job;

	this.diceSession.deleteJob(job);

	this.refresh();
}

SearchResultsPanel.prototype.refresh = function () {
	if (this.results.results.length > 0) {
		if (this.infoPanel.firstChild != null)
			this.infoPanel.removeChild (this.infoPanel.firstChild);

		var div = DIV();

		if (this.context.name == 'saved') {
			if (this.results.stale && this.companyPanel.getActiveCompanyName() != 'All Companies') {
				div.innerHTML = "showing <B><I>" + this.results.resultCount + "</I></B> saved jobs posted by <B>" + this.companyPanel.getActiveCompanyName() + "</B>";
			} else {
				div.innerHTML = "showing <B><I>" + this.results.resultCount + "</I></B> saved jobs";
			}
		} else {
			if (this.results.stale && this.companyPanel.getActiveCompanyName() != 'All Companies') {
				div.innerHTML = "showing <B><I>" + this.results.resultCount + "</I></B> jobs posted by <B>" + this.companyPanel.getActiveCompanyName() + "</B>";
			} else {
				div.innerHTML = "found <B><I>" + this.results.resultCount + "</I></B> jobs in the <B>" + this.mapPanel.location + "</B> area";
			}
		} 
		this.infoPanel.appendChild (div);

		this.renderPage();
		this.skillsPanel.setSkills(this.results.skills);
	} else {
		this.clearResults();
		if (this.infoPanel.firstChild != null)
			this.infoPanel.removeChild (this.infoPanel.firstChild);
		if (this.context.name == 'saved') {
			this.infoPanel.appendChild (DIV(null, "no saved jobs" ));
		} else {
			this.infoPanel.appendChild (DIV(null, "found no results in your area" ));
		}
	}

}

SearchResultsPanel.prototype.activeJobOnMap = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
	} else {
		target = window.event.srcElement;
	}

	var job = target.job;

	if (this.activeJob != null)
		this.deactivateJob (this.activeJob);

	this.activeJob = job;

	job.contentDiv.setAttribute ("class", "postContent postContentActive");
	job.contentDiv.setAttribute ("className", "postContent postContentActive");

	this.mapPanel.activateJob (job);
}

SearchResultsPanel.prototype.getDistance = function (job) {
	var centroid = this.mapPanel.centroid;
	if (centroid == null || centroid.latitude == null || centroid.longitude == null) {
		return "";
		job.distance = 1000000;
	}
	if (job.latitude != null && job.longitude != null) {
/*
		var R = 3958.75587; // Miles
		var dLat = (job.latitude - centroid.latitude) / 180.0 * 3.14159265;
		var dLon = (job.longitude - centroid.longitude) / 180.0 * 3.14159265;
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
			Math.cos(job.latitude / 180.0 * 3.14159265) * 
			Math.cos(centroid.latitude / 180.0 * 3.14159265) *
			Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
		var d = R * c;
		job.distance = d;
*/
/* */
		var jobPos = new GLatLng (job.latitude, job.longitude);
		var cenPos = new GLatLng (centroid.latitude, centroid.longitude);

		distance = jobPos.distanceFrom (cenPos) * 0.000621371192;

		job.distance = distance;
/* */ 
		if (job.distance < 10.0) {
			return " (in your area)";
		} else {
			return " (about " + Math.floor(job.distance) + " miles away)";
		}
	} else {
		return "";
	}
}

SearchResultsPanel.prototype.saveContext = function () {
	this.context.currentPage = this.currentPage;
	this.context.pageSize = this.pageSize;
	this.context.sortMethod = this.sortMethod;
	this.context.viewContext = this.diceSession.viewContext;
	this.context.activeJob = this.activeJob;
}

SearchResultsPanel.prototype.setContext = function (context) {
	this.context = context;

	this.currentPage = context.currentPage;
	this.pageSize = context.pageSize;
	this.sortMethod = context.sortMethod;

	this.skillRegistry = context.registry;
	this.skillsPanel.setRegistry (this.skillRegistry);

	this.results = context.results;

	this.companyPanel.setResults (this.results);

	// Update the skill registry:
	this.totalPages = (this.results.results.length % this.pageSize > 0) ? Math.floor(this.results.results.length / this.pageSize) + 1: this.results.results.length / this.pageSize;

	if (context.name == 'saved') {
		this.relevanceSpan.style.display = 'none';
		this.results.skills = this.getTopSkills (this.results.results);
	} else {
		this.relevanceSpan.style.display = 'inline';
	}

	var link = document.getElementById (context.sortMethod+"Link");
	if (link) {
		this.activeSortControl.setAttribute("class", "default");
		this.activeSortControl.setAttribute("className", "default");
		link.setAttribute("class", "active");
		link.setAttribute("className", "active");
		this.activeSortControl = link;
	}

	this.refresh();

	if (context.viewContext != this.diceSession.viewContext) {
		signal (this.diceSession, 'updateMenuViewContext', this.context.viewContext);

		this.switchViewContext (this.context.viewContext);
	}

	// Now activate the active job:
	this.activeJob = null;
	if (context.activeJob != null) {
		this.doHighlightJob (context.activeJob);
	}

}

SearchResultsPanel.prototype.switchContext = function (context) {
	this.saveContext();

	if (context == 'search') {
		this.setContext (this.diceSession.getSearchContext());
	} else if (context == 'save') {
		this.setContext (this.diceSession.getSavedContext());
	} else {
		alert ("No comparisons just yet, sorry!");
	}
}

SearchResultsPanel.prototype.switchViewContext = function (viewContext) {

}

SearchResultsPanel.prototype.showSummaries = function (show) {
	this.showSummary = show;

	var offset = (this.pageSize * (this.currentPage-1));
	var terminator = Math.min(offset+this.pageSize, this.results.results.length);

	if (this.activeJob != null && this.activeJob.viewMode == 'details') {
		blindUp (job.detailsDiv);
	}

	for (var i=offset; i < terminator; i++) {
		if (show) {
			this.results.results[i].viewMode = 'summary';
			blindDown (this.results.results[i].skillsDiv);
			blindDown (this.results.results[i].summaryDiv);
			if (this.activeJob != null && this.results.results[i].id == this.activeJob.id) {
				blindDown (this.results.results[i].topMenuDiv);
			}
		} else {
			this.results.results[i].viewMode = 'brief';
			blindUp (this.results.results[i].skillsDiv);
			blindUp (this.results.results[i].summaryDiv);
			if (this.activeJob != null && this.results.results[i].id == this.activeJob.id) {
				blindUp (this.results.results[i].topMenuDiv);
			}
		}
	}
}

SearchResultsPanel.prototype.getTopSkills = function (jobs) {
	var tmp = [];
	var arr = [];

	// First count the skill frequency	
	for (var i=0; i < jobs.length; i++) {
		//alert ("JOB: " + jobs[i].title + ", Skills: " + jobs[i].skills.length);
		for (var j=0; j < jobs[i].skills.length; j++) {
			if (!tmp[jobs[i].skills[j].name]) {
				tmp[jobs[i].skills[j].name] = {hits: 0, id: jobs[i].skills[j].id};
			}

			tmp[jobs[i].skills[j].name].hits++;
		}
	}

	// Create the structures
	for (var key in tmp) {
		arr.push ({name: key, id: tmp[key].id, hits: tmp[key].hits});
	}

	var s;
	// Next sort the array, numerically if more than 50 elements are
	// present:
	if (arr.length > 50) {
		for (var i=0; i < arr.length; i++) {
			for (var j=i+1; j < arr.length; j++) {
				if (arr[j].hits > arr[i].hits) {
					s = arr[i];
					arr[i] = arr[j];
					arr[j] = s;
				}
			}
		}

		arr = arr.slice (0, 50);
	} 

	// Now sort the array alphabetically:
	for (var i=0; i < arr.length; i++) {
		for (j=i+1; j < arr.length; j++) {
			if (arr[j].name < arr[i].name) {
				s = arr[i];
				arr[i] = arr[j];
				arr[j] = s;
			}
		}
	}

	return arr;
}

SearchResultsPanel.prototype.switchViewContext = function (viewContext) {
	if (this.diceSession.viewContext == viewContext) return;

	var contentWidth = DicejobsApp.contentWidth;

	if (this.diceSession.viewContext == 'map view') {
		appear(this.sortControls);
		Scale (this.content, this.getTargetWidthPercentage(this.content, 63), {scaleY: false, scaleContent: false});
		this.mapPanel.setExpandableWidth();
		Scale (this.rightSidebar, this.getTargetWidthPercentage(this.rightSidebar, 35), 
			{scaleY: false, scaleContent: false});
		this.mapPanel.expandMapToHeight(300);
		this.showSummaries (true);

		if (viewContext == 'summary view') {
			this.skillsPanel.blindDown();
		} else { // Company view
			this.mapPanel.fade();
			Move (this.content, {x: 300});
			// Now present the companies
			
			//this.companyPanel.setResults (this.results.results);
			appear (this.leftSidebar);
		}
	} else if (this.diceSession.viewContext == 'company view') {
		// Needs to be done to update skill cloud if a subset has been
		// selected
		if (this.results.stale && this.results.skills.length == 0) {
			this.results.skills = this.getTopSkills (this.results.results);
			this.skillsPanel.setSkills(this.results.skills);
		} //
		fade (this.leftSidebar);
		if (viewContext == 'map view') {
			fade(this.sortControls);
			Move (this.content, {x: -300});
			this.showSummaries(false);
			Scale (this.content, this.getTargetWidthPercentage(this.content, 33), {scaleY: false, scaleContent: false});
			this.mapPanel.setExpandableWidth();
			Scale (this.rightSidebar, this.getTargetWidthPercentage(this.rightSidebar, 66), 
				{scaleY: false, scaleContent: false, afterFinish: bind(this.mapPanel.updateMapSize, this)});
			var f = bind(function() {
				this.mapPanel.expandMapToHeight(DicejobsApp.info.winHeight - 220);
			}, this);
			this.mapPanel.appear(f);
			//this.mapPanel.expandMapToHeight(DicejobsApp.info.winHeight - this.content.style.top);
		} else { // Summary View
			Move (this.content, {x: -300});
			this.mapPanel.appear();
			this.skillsPanel.appear();
		} 
	} else {
		if (viewContext == 'map view') {
			fade (this.sortControls);
			this.skillsPanel.blindUp();
			this.showSummaries(false);

			// We want the content to be 33% of the screen:
			Scale (this.content, this.getTargetWidthPercentage(this.content, 33), {scaleY: false, scaleContent: false});
			this.mapPanel.setExpandableWidth();
			Scale (this.rightSidebar, this.getTargetWidthPercentage(this.rightSidebar, 66), 
				{scaleY: false, scaleContent: false, afterFinish: bind(this.updateMapSize, this)});

			this.mapPanel.expandMapToHeight(DicejobsApp.info.winHeight - 220);
		} else { // Company View
			//this.companyPanel.setResults (this.results.results);
			this.mapPanel.fade();
			this.skillsPanel.fade();
			Move (this.content, {x: 300});
			appear (this.leftSidebar);
			// Now present the companies
		}
	}

	this.diceSession.viewContext = viewContext;
}

SearchResultsPanel.prototype.getTargetWidthPercentage = function (element, winPercentage) {
	var percent = 0;

	var targetWidth = (this.content.offsetParent.clientWidth-20) * (winPercentage / 100.0);
	//alert ("Target Width: " + targetWidth);

	var currentWidth = element.clientWidth;
	//alert ("Current Width: " + currentWidth);

	percent = targetWidth / currentWidth * 100.0;

	//alert ("Scaling to " + percent + "%");
	return percent;

}

SearchResultsPanel.prototype.updateMapSize = function () {
	this.mapPanel.expandMapToWidth (this.rightSidebar.clientWidth - 6);
}
var SkillRegistry = function () {
	this.registry = {};
	this.expiration = 0;
}

SkillRegistry.prototype.registerSkill = function (skillLink) {
	skillLink.onclick = bind(this.toggleState, this);
	var skill = skillLink.firstChild.nodeValue;
	//alert ("Registering skill: " + skill);

	if (!this.registry[skill]) {
		this.registry[skill] = {links: [], state: 'normal', id: skillLink.skill.id};
	} else if (this.registry[skill].state == 'highlighted') {
		skillLink.setAttribute ("class","tagHighlighted");
		skillLink.setAttribute ("className","tagHighlighted");
	}

	this.registry[skill].links.push (skillLink);
}

SkillRegistry.prototype.clearRegisteredJobTags = function () {
	for (key in this.registry) {
		this.registry[key].links.splice(1, this.registry[key].links.length-1);
	}
}

SkillRegistry.prototype.clearRegistry = function () {
	for (key in this.registry) {
		this.registry[key].links.splice(0, this.registry[key].links.length);
	}
}

SkillRegistry.prototype.getHighlightedSkills = function (topSkills) {
	var skills = [];

	var found;
	for (key in this.registry) {
		if (this.registry[key].state != 'highlighted') continue;
		found = false;
		
		for (var i=0; i < topSkills.length; i++) {
			if (topSkills[i].name == key) {
				found = true;
				break;
			}
		}

		if (!found) {
			var s = {name: key, hits: 0, id: this.registry[key].id};
			skills.push (s);
		}
	}
	return skills;
}

SkillRegistry.prototype.highlightSkill = function (skill) {
	if (this.registry[skill]) {
		if (this.registry[skill].state == 'normal') {
			this.registry[skill].state = 'highlighted';
			className = '';
			for (var i=0; i < this.registry[skill].links.length; i++) {
				this.registry[skill].links[i].setAttribute("class", className);
				this.registry[skill].links[i].setAttribute("className", className);
			}
		}
	}

}

SkillRegistry.prototype.toggleState = function (e) {
	var skill;

	if (e != undefined) {
		skill = e.target.textContent;
	} else {
		skill = window.event.srcElement.firstChild.nodeValue;
	}

	if (this.registry[skill]) {
		var className = '';
		if (this.registry[skill].state == 'normal') {
			this.registry[skill].state = 'highlighted';
			className = 'tagHighlighted';
		} else {
			this.registry[skill].state = 'normal';
			className = 'tag';
		}
		for (var i=0; i < this.registry[skill].links.length; i++) {
			this.registry[skill].links[i].setAttribute("class", className);
			this.registry[skill].links[i].setAttribute("className", className);
		}
	}

	var d = new Date();
	this.expiration = d.getTime() + 1000;

	setTimeout (bind(this.updateSearch, this), 1010); // Because of lame resolution issues
}

SkillRegistry.prototype.updateSearch = function () {
	var d = new Date();
	if (this.expiration > d.getTime()) {
		return; // Another event has been triggered
	}

	// We need a way to lock the skills to prevent further "clicking" at
	// this point.

	var skills = new Array();

	for (key in this.registry) {
		if (this.registry[key].state == 'highlighted')
			skills.push(this.registry[key].id);
	}

	var text = "";
	if (skills.length > 1) {
		text += skills[0];
		
		for (var i=1; i < skills.length; i++) {
			text += "+" + skills[i];
		}

	}
	signal(this, "refresh", true, "skills", text);
}

SkillRegistry.prototype.filterResults = function () {
}
var SkillsPanel = function () {
	this.skills = [];
	this.alphaSort = true;
	this.showHits = false;

	this.skillRegistry = null;
}

SkillsPanel.prototype.setRegistry = function (registry) {
	this.skillRegistry = registry;
}

SkillsPanel.prototype.paint = function () {
	var lnk = A ({href:"javascript:void(0);", "class":"not-popular"}, "click me");
	lnk.onclick = bind(this.checkDimensions, this);
	
	this.dTmp = SPAN({"class":"title"}, "top skills");
	this.cloud = LI(null, DIV(null, this.dTmp, ": "));

	this.selectedCloud = LI({style:"display:none;"});

	this.sortAlpha = A({href:"javascript:void(0);", "class":"active"}, "alpha");
	this.sortAlpha.onclick = bind(this.changeSortOrder, this);
	this.sortFreq = A({href:"javascript:void(0);"}, "frequency");
	this.sortFreq.onclick = bind(this.changeSortOrder, this);

	this.hitsShow = A({href:"javascript:void(0);"}, "show");
	this.hitsShow.onclick = bind(this.changeHitVisibility, this);
	this.hitsHide = A({href:"javascript:void(0);", "class":"active"}, "hide");
	this.hitsHide.onclick = bind(this.changeHitVisibility, this);

	this.controls = UL({"class":"menu"},
				LI(null, 
					SPAN({"class":"title"}, "options: "), 
					UL({"class":"submenu"}, 
						LI(null, "sort by: ", this.sortAlpha, " | ", this.sortFreq),
						LI(null, "match count: ", this.hitsShow, " | ", this.hitsHide)
					)
				)
			); 
	var cloudList = UL({"class":"menu"}, this.cloud, this.selectedCloud);
	this.element = DIV({"class":"element"}, cloudList, this.controls);

	return this.element;
}

SkillsPanel.prototype.checkDimensions = function (e) {
	alert (e.type);
	if (this.maxWidth == null) {
		this.maxWidth = this.cloud.offsetWidth;
		this.maxHeight = this.cloud.offsetHeight;
		alert ("Heights: (offset): " + this.dTmp.offsetHeight + " (client): " + this.dTmp.clientHeight);
	}
	alert ("Max Width: " + this.maxWidth + ", Max Height: " + this.maxHeight);
}

SkillsPanel.prototype.changeSortOrder = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}

	if (txt == "alpha") {
		this.alphaSort = true;
		this.sortAlpha.setAttribute("class","active");
		this.sortAlpha.setAttribute("className","active");
		this.sortFreq.setAttribute("class","default");
		this.sortFreq.setAttribute("className","default");
	} else {
		this.alphaSort = false;
		this.sortAlpha.setAttribute("class","default");
		this.sortAlpha.setAttribute("className","default");
		this.sortFreq.setAttribute("class","active");
		this.sortFreq.setAttribute("className","active");
	}

	this.renderSkills();
}

SkillsPanel.prototype.changeHitVisibility = function (e) {
	var target, txt;

	if (e != undefined) {
		target = e.target;
		txt = target.textContent;
	} else {
		target = window.event.srcElement;
		txt = target.firstChild.nodeValue;
	}

	if (txt == "show") {
		this.showHits = true;
		this.hitsShow.setAttribute("class","active");
		this.hitsShow.setAttribute("className","active");
		this.hitsHide.setAttribute("class","default");
		this.hitsHide.setAttribute("className","default");
	} else {
		this.showHits = false;
		this.hitsShow.setAttribute("class","default");
		this.hitsShow.setAttribute("className","default");
		this.hitsHide.setAttribute("class","active");
		this.hitsHide.setAttribute("className","active");
	}

	this.renderSkills();
}

SkillsPanel.prototype.setSkills = function (skills) {
	
	if (this.maxWidth == null) {
		this.maxWidth = this.cloud.offsetWidth;
		this.maxHeight = (this.cloud.offsetHeight > 0) ? this.cloud.offsetHeight : 15;
	}

	this.skills = skills;

	this.renderSkills();
}

SkillsPanel.prototype.refresh = function () {
	this.renderSkills();
}


SkillsPanel.prototype.clearSkills = function () {
	while (this.cloud.firstChild != null)
		this.cloud.removeChild (this.cloud.firstChild);

	while (this.selectedCloud.firstChild != null)
		this.selectedCloud.removeChild (this.selectedCloud.firstChild);
}

SkillsPanel.prototype.renderSkills = function () {
	var skills;

	if (this.alphaSort) {
		skills = this.skills;
	} else {
		skills = this.getSortedArray();
	}

	this.clearSkills();

	var idx = 0;
	var done = false;

	var list = UL({"class":"tagcloud"});
	var div = DIV(null, SPAN({"class":"title"}, "top skills"), ": ", list);

	this.cloud.appendChild (div);

	if (skills.length == 0) return;

	while (!done) {
		var skill = LI(null, this.renderSkill(skills[idx++]));

		list.appendChild (skill);

		if (list.offsetWidth > this.maxWidth || list.offsetHeight > this.maxHeight) {
			//alert ("Creating a new row: " + list.offsetWidth  + " > " + this.maxWidth);
			list.removeChild (skill);
			list = UL({"class":"tagcloud"});
			div = DIV(null, list);
			this.cloud.appendChild (div);
			list.appendChild (skill);
		}

		if (idx >= skills.length) {
			done = true;
		}
		//alert ("stepping...");
	}

	// Now we might need to repeat this if we have skills highlighted with
	// no links
	
	skills = this.skillRegistry.getHighlightedSkills(this.skills);
	if (skills.length > 0) {
		idx = 0;
		done = false;

		list = UL({"class":"tagcloud"});
		div = DIV(null, SPAN({"class":"title"}, "selected skills"), ": ", list);

		this.selectedCloud.appendChild (div);

		while (!done) {
			var skill = LI(null, this.renderSkill(skills[idx++]));
	
			list.appendChild (skill);
	
			if (list.offsetWidth > this.maxWidth || list.offsetHeight > this.maxHeight) {
				list.removeChild (skill);
				list = UL({"class":"tagcloud"});
				div = DIV(null, list);
				this.selectedCloud.appendChild (div);
				list.appendChild (skill);
			}

			if (idx >= skills.length) {
				done = true;
			}
		}
		this.selectedCloud.style.display = 'block';
	} else {
		this.selectedCloud.style.display = 'none';
	}

}

SkillsPanel.prototype.renderSkill = function (skill) {
	var link = A({"class":"not-popular", href:"javascript:void(0);"}, skill.name);
	link.skill = skill;
	this.skillRegistry.registerSkill (link);

	if (this.showHits) {
		var hits = SPAN({"class":"light-comment"}, " (" + skill.hits + ")");
		return LI(null, link, hits);
	} else {
		return LI(null, link);
	}
}

SkillsPanel.prototype.removeSkills = function () {
	while (this.cloud.firstChild != null) {
		this.cloud.removeChild (this.cloud.firstChild);
	}
}

SkillsPanel.prototype.getSortedArray = function () {
	var arr = [];
	for (var i=0; i < this.skills.length; i++) {
		arr[i] = this.skills[i];
	}

	var tmp;
	for (var i=0; i < this.skills.length; i++) {
		for (j=i+1; j < this.skills.length; j++) {
			if (arr[j].hits > arr[i].hits) {
				tmp = arr[i];
				arr[i] = arr[j];
				arr[j] = tmp;
			}
		}
	}

	return arr;
}

SkillsPanel.prototype.fade = function () {
	fade (this.element);
}

SkillsPanel.prototype.blindUp = function () {
	blindUp (this.element);
}

SkillsPanel.prototype.blindDown = function () {
	blindDown (this.element, {beforeStart: bind(this.clearSkills, this), afterFinish: bind(this.refresh, this)});
}

SkillsPanel.prototype.appear = function () {
	appear (this.element, {beforeStart: bind(this.clearSkills, this), afterFinish: bind(this.refresh, this)});
}
