var Geotools = {
	makeFeatureObject: function(table, feature, useDefaultText) {
		if(feature == null) return null;
		var obj = {};
		table.columns.each(function(c, i) {
			obj[c] = useDefaultText ? feature[i] || config.defaultText : feature[i];
		});
		if(table.relatedTable) {
			var fk = obj[table.foreignKey];
			var relatedTable = window[table.relatedTable];
			var pkIndex = relatedTable.columns.indexOf(table.primaryKey);
			if(pkIndex == -1) return obj;
			var relatedFeature = relatedTable.features.find(function(f) {
				return f[pkIndex] == fk;
			});
			if(relatedFeature) {
				relatedTable.columns.each(function(c, i) {
					if(c == "id") c = table.relatedTable + "_id";
					obj[c] = useDefaultText ? relatedFeature[i] || config.defaultText : relatedFeature[i];
				});
			}
		}
		return obj;
	},
	findFeature: function(table, id) {
		return Geotools.findFeatureBy(table, "id", id);
	},
	findFeatureBy: function(table, column, id) {
		var colIndex = table.columns.indexOf(column), colId = id.toString();
		return table.features.find(function(feature) {
			return feature[colIndex] == colId;
		});
	},
	getFeatureObject: function(table, id, useDefaultText) {
		return Geotools.makeFeatureObject(table, Geotools.findFeature(table, id), useDefaultText);
	},
	getFeatureObjectBy: function(table, column, id, useDefaultText) {
		return Geotools.makeFeatureObject(table, Geotools.findFeatureBy(table, column, id), useDefaultText);
	},
	getRelatedFeatures: function(table, feature, useDefaultText) {
		var pk = feature[table.primaryKey];
		var fkIndex = table.columns.indexOf(table.foreignKey);
		if(fkIndex == -1) {
			return [];
		}
		var features = [];
		table.features.each(function(f) {
			if(f[fkIndex] == pk) {
				features.push(Geotools.makeFeatureObject(table, f, useDefaultText));
			}
		});
		return features;
	},
	getCategories: function(table, features) {
		var categories = [];
		features.each(function(f) {
			if(!f.id) f = Geotools.makeFeatureObject(table, f);
			var c = f[config.categoryColumn];
			var cat = categories.find(function(n) {
				return n.category == c;
			});
			if(!cat) {
				cat = { category: c, features: [] };
				categories.push(cat);
			}
			cat.features.push(f);
			f.link = 'return featureClick(' + f.id + ');';
		});
		categories.each(function(c) {
			c.count = c.features.length;
			c.link = 'return categoryClick("' + c.category + '");';
		});
		return categories;
	},
	getPoint: function(feature) {
		var shape;
		if(feature.shape) {
			shape = feature.shape;
		} else {
			shape = feature[feature.length - 1];
		}
		if(shape.length == 0) return null;
		var point = shape[0];
		return new GLatLng(point[0], point[1]);
	},
	getPoints: function(feature) {
		var shape;
		if(feature.shape) {
			shape = feature.shape;
		} else {
			shape = feature[feature.length - 1];
		}
		var points = [];
		shape.each(function(point) {
			points.push(new GLatLng(point[0], point[1]));
		});
		return points;
	},
	createMarker: function(table, feature, callbacks, iconImage) {
		var point = Geotools.getPoint(feature);
		var iconIndex = table.columns.indexOf(config.iconColumn);
		if(!iconImage) {
			iconUrl = feature[iconIndex] ? config.iconBase + feature[iconIndex] : null;
		} else {
			iconUrl = config.iconBase + iconImage;
		}
		if(!point) return;
		var icon = new GIcon(baseIcon);
		if(iconUrl) icon.image = iconUrl;
		var marker = new GMarker(point, icon);
		if(callbacks) {
			$H(callbacks).each(function(e) {
				GEvent.addListener(marker, e.key, e.value);
			});
		}
		return marker;
	},
	createPolyline: function(table, feature, callbacks) {
		var colorIndex = table.columns.indexOf(config.colorColumn);
		var color = feature[colorIndex] ? "#" + feature[colorIndex] : null;
		var points = Geotools.getPoints(feature);
		var polyline = new GPolyline(points, color || config.strokeColor, config.strokeWeight, config.strokeOpacity);
		if(callbacks) {
			$H(callbacks).each(function(e) {
				GEvent.addListener(polyline, e.key, e.value);
			});
		}
		return polyline;
	},
	createPolygon: function(table, feature, callbacks) {
		var colorIndex = table.columns.indexOf(config.colorColumn);
		var color = feature[colorIndex] ? "#" + feature[colorIndex] : null;
		var points = Geotools.getPoints(feature);
		var polygon = new GPolygon(points, color || config.strokeColor, config.strokeWeight, config.strokeOpacity, color || config.fillColor, config.fillOpacity);
		if(callbacks) {
			$H(callbacks).each(function(e) {
				GEvent.addListener(polygon, e.key, e.value);
			});
		}
		return polygon;
	}
};
