#!/usr/bin/perl
#
# Have a conversation with Eliza
#

# ***********************************************************
# You should edit these variables to reflect your environment:

# URL to the Code Collaborator Server
$CCOLLAB_URL = "http://localhost:8080";

# Login of Code Collaborator User who Eliza will use for chat
# should be a Code Collaborator administrator
$CCOLLAB_USER = "eliza";

# Password of Code Collaborator User who Eliza will use for chat
$CCOLLAB_PASSWORD = "eliza";

# Seconds to sleep before polling for new chat
$REFRESH_DELAY_SECONDS = 4;

#***********************************************************

# Options to connect to Code Collaborator
$ccollabOptions = "--url $CCOLLAB_URL";
$ccollabOptions .= " --user $CCOLLAB_USER";
$ccollabOptions .= " --password \"$CCOLLAB_PASSWORD\"";
$ccollabOptions .= " --quiet --non-interactive";

#
# usage: eliza.pl <review-id> <defect-id>
#

use Chatbot::Eliza;
use IPC::Open2;

# read parameters from command-line
$reviewId = $ARGV[0];
$defectId = $ARGV[1];

#xslt file we will use to extract info from Code Collaborator
$xslt = <<XSLT;
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
	
	<xsl:template match='//reviews/review'>
	
		<!--  get review phase -->
		<xsl:value-of select='general/phase'/><xsl:text>
</xsl:text>
		
		<!--  find defect -->
		<xsl:for-each select='defects/defect[\@defectId=$defectId]'>
	
			<!--  get defect status -->
			<xsl:value-of select='status'/><xsl:text>
</xsl:text>
	
			<!--  get defect text-->
			<xsl:value-of select='text'/><xsl:text>
</xsl:text>

		</xsl:for-each>
			
		<!--  find the conversation we're talking on (the one with the defect) -->
		<xsl:for-each select='conversations/conversation[defects/conversation-defect/\@defect-id=$defectId]'>
		
			<!-- find last comment in conversation -->
			<xsl:for-each select='comments/comment[last()]'>
			
				<!--  get author -->
				<xsl:value-of select='\@creator'/><xsl:text>
</xsl:text>
				
				<!--  get text -->
				<xsl:value-of select='text()'/><xsl:text>
</xsl:text>
			
			</xsl:for-each>

			<!-- get file-path (empty for overall comment) -->
			<xsl:value-of select='\@file-path'/><xsl:text>
</xsl:text>
			
			<!-- get line-number (empty for overall comment or file overall comment) -->
			<xsl:value-of select='\@line-number'/><xsl:text>
</xsl:text>
			
		</xsl:for-each>
		
	</xsl:template>
</xsl:stylesheet>
XSLT

# initialize Eliza
$eliza = new Chatbot::Eliza;

while (1) {

	# sleep so we don't hammer the server
	sleep($REFRESH_DELAY_SECONDS);

	# Query Code Collaborator server for info
	$pid = open2(*CCOLLAB_OUTPUT, *XSL_INPUT, "ccollab $ccollabOptions admin review-xml $reviewId --xsl-file -");
	print XSL_INPUT $xslt;
	close(XSL_INPUT);
	chomp(($spacer, $reviewPhase, $defectStatus, $defectText, $author, $inputChat, $filePath, $lineNumber) = <CCOLLAB_OUTPUT>);
	close(CCOLLAB_OUTPUT);
	waitpid($pid,0);
	
	#cleanup filePath and lineNumber
	chop($filePath);
	chop($lineNumber);
	
	#debug
	print "reviewPhase = $reviewPhase\n";
	print "defectStatus = $defectStatus\n";
	print "defectText = $defectText\n";
	print "author = $author\n";
	print "inputChat = $inputChat\n";
	print "filePath = \"$filePath\"\n";
	print "lineNumber = \"$lineNumber\"\n";
	print "\n";
	
	# safety -  quit if review isn't in Inspection phase
	die ("Review is no longer in Inspection phase") if ($reviewPhase !~ /Inspection/);
		
	# safety - quit if defect isn't open
	die ("Defect $defectId is no longer open") if ($defectStatus !~ /open/);		
		
	# safety - quit if defect text doesn't mention "Eliza"
	die ("Defect $defectId text doesn't mention Eliza") if ($defectText !~ /Eliza/);		
		
	# Eliza shouldn't respond to system messages, like "** Marked Read **" or "** Accepted **"
	next if ($inputChat =~ /^\*\*/);
	
	# Eliza shouldn't talk to herself
	next if ($author =~ /$CCOLLAB_USER/);
	
	# Get response from Eliza
	$outputChat = $eliza->transform($inputChat);
	
	#debug
	print "$outputChat\n"; 
	print "\n";
	
	# build command to upload Eliza's comment to Code Collaborator
	$uploadCommand = "ccollab $ccollabOptions admin review comment create $reviewId \"$outputChat\"";
	
	# file path is optional (no file path for overall review chat)
	if ($filePath) {
		$uploadCommand .= " --file \"$filePath\"";
	}
	
	# line number is optional (no line number for overall review chat or overall file chat)
	if ($lineNumber) {
		$uploadCommand .= " --line-number $lineNumber";
	}

	#debug
	print "Running $uploadCommand\n";
		
	# upload Eliza's comment to Code Collaborator
	system("$uploadCommand");

}