=begin rdoc
Lemmatizer: Helper module to enable communication between Rails interface,
Plain lemmatizer and Blender via TCP sockets.
Start a server on the host for the lemmatizer, listen for client calls, run lemmatizer with query as input return the processed query.

Author:: Stephanie Schuldes (schuldes@cl.uni-heidelberg.de)
Project:: iCookWare
Copyright:: iCookWare Team 2005 (Nicola Kaiser, Ana Kovatcheva, Olga Mordvinova, Stephanie Schuldes)
Embedded Documentation Tool:: rdoc
=end

require 'socket'
require 'timeout'

module ICW
	class Lemmatizer
	
		# Initialize a new instance of Lemmatizer.
		# +port+:: number of port for communication with clients, by default 23000
		def initialize(port=23000)
			@rawIngreds = Array.new
			@lemmata = Array.new
			@server = TCPServer::new("", port)
			print "Server started on port ", port, "\n"
		end
		
		# Core method: Receive client requests, call lemmatize method and return
		# processed ingredients to client.
		def run
			# wait for connection
			begin
				while(session = @server.accept)
					puts "connection"
					@rawIngreds.clear
					#rawIngreds = Array.new
					request = String.new
					
					begin
						timeout(6) do
							begin
								# receive as long as there is still data to read
								while((data = session.recv(4096)) != "\n")
									puts "data comin"
									request.concat(data)
								end
							rescue SystemCallError, IOError
								$stderr.print "Read from stream failed: " + $!
							end
						end
					rescue TimeoutError => e
						$stderr.puts "Caught #{e.class}: #{e}"
						exit(1)
					end	
						
					puts "SERVER: Received request"
					@rawIngreds = Marshal.load(request)
					puts @rawIngreds
									
					# call lemmatize method
					@lemmata = self.lemmatize(@rawIngreds)
					
					# return result to client
					puts "SERVER: Returning result to client... ", @lemmata, "\n"
					lemmaData = Marshal.dump(@lemmata)
					session.puts(lemmaData)
					session.write("\n")
				end
			rescue Interrupt
				puts "Bye!"
				ensure
					@server.close
				exit(1)
			end
		end
		
		# Call Plain lemmatizer for every ingredient in the array received
		# from the client. Read the result from output file of the lemmatizer
		# and return the new list.
		# +rawList+:: Array with unprocessed ingredient strings received from client
		def lemmatize(rawList)
			puts "SERVER: Lemmatizing..."
			ingredList = Array.new
						
			# call Plain lemmatizer
			p = IO.popen("./lemmatize", "w+")
			rawList.each do | ingr |
				p.puts(ingr)
			end
			p.close_write
			p.close_read
			
			# read from lemma file (since stdout cannot be used)
			if File.exists? "lemmata.txt"
				f = File.open("lemmata.txt", "r")
				f.each_line do | line |		
					ingredList.push(line)
				end
				f.close
			else
				puts "No such file!"
			end
				
			return ingredList
		
		end		
	end
end

myLemmatizer = ICW::Lemmatizer.new
myLemmatizer.run