#!/usr/bin/perl
# 
# select.pl
# (c) 2007 Dan "Ducky" Little for OpenMNND
# This script works with GeoMOOSE to perform selection operations.

use strict;
use mapscript;
use CGI;

# THIS IS THE POINTER TO THE SELECT.MAP FILE!
my $queryMapFile = '/ms4w/apps/GeoMOOSE/maps/select.map';

# This is the default delimiter in case it's not passed in from the CGI
my $defaultDelim = ':';

# New CGI Object
my $cgi = new CGI;

# Coordinates, in ground units, and the title
my $coordinates = $cgi->param('coords');
my $title = $cgi->param('title');
my $shapeType = $cgi->param('shape');
my $buffer = $cgi->param('buffer');

my $layer = $cgi->param('layer');
#my $queryColumn = $cgi->param('column');
my $delim = $cgi->param('delim');

if(not $delim) {
	$delim = $defaultDelim;
}

my $queryColumn;

($layer, $queryColumn) = split(/$delim/, $layer);


if(not (-e $queryMapFile)) {
	&appError('Could not find: '.$queryMapFile);
}

if($shapeType =~ m/point/i) {
	$shapeType = $mapscript::MS_SHAPE_POINT;
} elsif($shapeType =~ m/circle/i) {
} elsif($shapeType =~ m/line/i) {
	$shapeType = $mapscript::MS_SHAPE_LINE;
	if(not $buffer) {
		$buffer = 1;	# Makes the line work
	}
} else {
	$shapeType = $mapscript::MS_SHAPE_POLYGON;
}

# Convert the coordinates to a new shape object
my $shape = mapscript::shapeObj->new($shapeType);
my @coords = split(/ /, $coordinates);
my $line = mapscript::lineObj->new();
foreach my $coord (@coords) {
	my ($x, $y) = split(/,/,$coord);
	my $point = mapscript::pointObj->new();
	$point->{x} = $x;
	$point->{y} = $y;
	$line->add($point);
}
$shape->add($line);

$shape->setBounds();
# Buffer as desired.
if($buffer) {
	$shape = $shape->buffer($buffer);
	if(not $shape) { 
		&appError("Buffering Failed. Buffer size: $buffer. Verify mapscript was linked with GEOS and that the buffer is a positive-real number.");
	}
}


# Create a new Coordinate string based on any potential buffering.
my $coordString = '';
for(my $line = 0; $line < $shape->{numlines}; $line++) {
	my $lineObj = $shape->get($line);
	for(my $point = 0; $point < $lineObj->{numpoints}; $point++) {
		my $pointObj = $lineObj->get($point);
		$coordString .= $pointObj->{x}.' '.$pointObj->{y}.' ';
	}
}

# Set up the query to perform the select, with the buffer and all!
my $queryMap = new mapscript::mapObj($queryMapFile) or &appError('Could not open mapfile: '.$queryMapFile);

my $queryLayerFound = undef;
for(my $l = 0; $l < $queryMap->{numlayers}; $l++) {
	my $queryLayer = $queryMap->getLayer($l);
	$queryLayer->{status} = $mapscript::MS_OFF;
	if($queryLayer->{name} eq $layer) {
		$queryLayer->{status} = $mapscript::MS_ON;
		$queryLayerFound = 1;
	}
}

if(not $queryLayerFound) {
	&appError("The Query Layer '$layer' could not be found in the mapfile ($queryMapFile).");
}

my $queryResultCheck = $queryMap->queryByShape($shape);
if($queryResultCheck == $mapscript::MS_FAILURE) {
	&appError('Query Failed to return any results!');
}

my @resultContents = ();

for(my $l = 0; $l < $queryMap->{numlayers}; $l++) {
	my $queryLayer = $queryMap->getLayer($l);
	if($queryLayer->{name} eq $layer) {
		my $queryResults = $queryLayer->getResults();
		my %queryColumns;

		$queryLayer->open();

		for(my $item = 0; $item < $queryLayer->{numitems}; $item++) {
			$queryColumns{$queryLayer->getItem($item)} = $item;
		}

		if($queryResults) {
			for(my $result = 0; $result < $queryResults->{numresults}; $result++) {
				my $queryResult = $queryResults->getResult($result);
				my $queryFeature = $queryLayer->getFeature($queryResult->{shapeindex}, $queryResult->{tileindex});
				my $v = $queryFeature->getValue($queryColumns{$queryColumn});
				push(@resultContents, $v);
			}
		}
		$queryLayer->close();
	}
}

print "Content-type: text/xml\n\n";
print qq(<return>
	<map title="$layer" default="true">
	<param name="mapshape" value="$coordString"/>
);

foreach my $id (@resultContents) {
	print "\t\t<selected id='$id'/>\n";
}

print "\t</map>";

print qq(
	<results title="Select Results">
		<header><col value="Selected Objects:"/></header>
		<row><col value="$#resultContents"/></row>
	</results>
);

# Process the query template from the mapfile and return it to the user
my $template = $queryMap->processQueryTemplate(undef,undef, 0);
print $template;

print "</return>";

#
# Prints an Error
#
sub appError($) {
	my $msg = shift();
#	print "Content-type: text/plain\n\n";
#	print "Select.pl Application Error.\n\n$msg\n";
print "Content-type: text/html\n\n";
	print qq(
<html>
	<head><title>GeoMOOSE Selection Error</title></head>
<body>
<h3>Selection Service Message</h3>
<b style="color:red">$msg</b>
</body>
</html>
);
	exit;
}
