/************************************************************************
 * This library is free software; you can redistribute it and/or        *
 * modify it under the terms of the GNU Library General Public          *
 * License as published by the Free Software Foundation; either         *
 * version 2 of the License, or (at your option) any later version.     *
 *                                                                      *
 * This library is distributed in the hope that it will be useful,      *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 * Library General Public License for more details.                     *
 *                                                                      *
 * You should have received a copy of the GNU Library General Public    *
 * License along with this library; if not, write to the                *
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,         *
 * Boston, MA  02111-1307, USA.                                         *
 *                                                                      *
 * The GNU Library General Public License file is included in           *
 * Online-Documentation                                                 *
 *                                                                      *
 * GNU's Homepage - http://www.gnu.org/                                 *
 *                                                                      *
 * Questions & comments referring to Hexi: please contact us:           *
 *                                                                      *
 * eMail:                                                               *
 *      ramsey@dbai.tuwien.ac.at                                        *
 * WWW:                                                                 *
 *      http://www.dbai.tuwien.ac.at/proj/ramsey/                       *
 *                                                                      *
 * (c) Wolfgang Slany 1987, Bidan Zhu 1996, Andreas Beer 1999           *
 * HexiServerThread.java             Version 2.10            24.08.1999 *
 ***********************************************************************/

import java.net.*;
import java.io.*;

public class HexiServerThread extends Thread
{
	final static byte LEARN_FACTOR = 14;
	final static byte NOT_READY = 0;
	final static byte READY_FOR_INSERT = 1;
	final static byte FINISHED = 2;
	Socket socket = null;
	double security = 70389367930;
	double number = 0; // number from HexiClient
	/* If security and number differ, the date, time and (if possible) the name and score of the cheater are sent to ramsey@dbai.tuwien.ac.at */
	private RandomAccessFile FileMem;
	private DataInputStream fileIN;
	private String PlayerName;
	private long Score;
	private int key;
	private boolean Mode, Multi;
	private String line;
	private PrintStream fileOut;
	private byte status;
	private String MarkBegin, MarkEnd;

	HexiServerThread(Socket clientSocket)
	{
		super("HexiServerThread");
		socket = clientSocket;
	}

	public void run()
	{
		System.out.println ("HexiServerThread netIN running. ") ;
		try
		{
			DataInputStream  netIN = new DataInputStream(socket.getInputStream());			
			number = netIN.readDouble(); // Receive number from HexiClient
			Mode = netIN.readBoolean();
			Multi = netIN.readBoolean();
			if (security == number)
			{
				// If message really is from a client
				if (Mode)
				{
					// Key Transfer
					System.out.println("Update winner begins");
					if (Multi) FileMem = new RandomAccessFile("hexi.mem1","rw");
					else FileMem = new RandomAccessFile("hexi.mem2","rw");
					while ((key=netIN.readInt())!=0)
					{
						FileMem.seek(Math.abs(key));
						byte w = FileMem.readByte();
						if (key > 0)
						{
							if (w < 126-LEARN_FACTOR) w += LEARN_FACTOR;
 							else w = 126;
						}
						else
						{
							if (w > -128+LEARN_FACTOR) w -= LEARN_FACTOR;
							else w = -128;
						}
						FileMem.seek(Math.abs(key));
						System.out.println("Server write key "+Math.abs(key)+" data "+w);
						FileMem.writeByte(w);
					} // while
					FileMem.close();
					System.out.println("Thread(Keytransfer) "+this.hashCode()+" is stopped!");
				} // if (Key Transfer)
				else
				{
					// Hall of Fame
					PlayerName = netIN.readLine();
					Score = netIN.readLong();
					System.out.println("Server read name "+PlayerName+" with score "+Score);

					/* If the player is using an older version of Netscape, it
					is possible that the "Add to Hall of Fame?"-inquiry is displayed
					at the very beginning. Since the resulting Score of 0 is not
					possible under normal conditions, the following query is
					necessary. */

					if (Score == 0) System.out.println("Score 0 not accepted");
					else
					{
						fileIN = new DataInputStream(new FileInputStream("Fame.htm"));
						fileOut = new PrintStream(new FileOutputStream("F.htm"));
  						if (Multi)
						{
							MarkBegin = "<!--multi -->";
							MarkEnd = "<!--end of multi -->";
						}
						else
						{
							MarkBegin = "<!--single -->";
							MarkEnd = "<!--end of single -->";
						}
						status = NOT_READY;
						while ((line=fileIN.readLine())!= null)
						{
							if (status == NOT_READY)
							{
								if (line.startsWith(MarkBegin)) status = READY_FOR_INSERT;
							}
							else if (status == READY_FOR_INSERT)
							{
								if (line.startsWith(MarkEnd)) status = FINISHED;
								else
								{
									int from = line.lastIndexOf("Score")+7;
									int to = line.lastIndexOf("</LI>");
									String s = line.substring(from,to);
									Long l = new Long(s);
									System.out.println("Score "+l);
									if (Score <= l.longValue() )  status = FINISHED;
								}
								if (status == FINISHED) fileOut.println("<LI> Name: "+PlayerName+" Score: "+Score+"</LI>");
							}
							fileOut.println(line);
						} // while
						fileIN.close();
						fileOut.close();
						fileIN = new DataInputStream(new FileInputStream("F.htm"));
						fileOut = new PrintStream(new FileOutputStream("Fame.htm"));
  						while ((line=fileIN.readLine())!= null) fileOut.println(line);
						fileIN.close();
						fileOut.close();
						System.out.println("Thread(HallofFame) "+this.hashCode()+" is stopped!");
					} // else (Score != 0)
				} // else (Hall of Fame)
			} // if (security == number)
			else
			{
				// Message is a fake
				System.out.println("Somebody tried to fake a message!");
				if (Mode)
				{
					while (netIN.readInt()!=0) { } // discard info
				}
				else
				{
					PlayerName = netIN.readLine();	// for the record
					Score = netIN.readLong();	//
				}
				/* For reasons unknown to me the current time for Java is 90 minutes ahead of the current time for the System.
				It might have something to do with that whole UPS, GMT and leap seconds business ... */
				CommandExec ex= new CommandExec("/usr/lib/sendmail -oi -oem -t");
				ex.println("To: ramsey@dbai.tuwien.ac.at");	// While testing it should be "beer@dbai.tuwien.ac.at".
										// While running in earnest it should be "ramsey@dbai.tuwien.ac.at".
				ex.println("From: HEXI");
				ex.println("Subject: HEXI-cheater caught!\n");
				// the extra newline \n above is required to separate the 
				// body of the message from the message header
				if (Mode)
				{
					ex.println("Tried to fake learning info");
					ex.println("No Name");
					ex.println("No Score");
				}
				else
				{
					ex.println("Tried to fake a highscore");
					ex.println("Name: "+PlayerName);
					ex.println("Score: "+Score);
				}
				ex.close(false);
			} // else (Message is a fake)
			netIN.close();
			socket.close();
		} // try
		catch (IOException e)
		{
			System.err.println("HexiServerThread: Couldn't get I/O for the connection!");
		}
	} // run

} // HexiServerThread