/*
 *	EasyScout Boy Scouts of America tracking software.
 *	http://www.easyscout.org/
 *
 *	Copyright (C) 2000 Conan C. Albrecht
 *	conan@warp.cx
 *
 *	This program is released under the GNU license so tech-savvy
 *	Boy Scouts and others can enhance the program for the use
 *	of all.  Please e-mail changes to my address above so I can
 *	reintegrate into the main program at http://www.easyscout.org/.
 *	This way, all users mutually benefit one another in the spirit of
 *	scouting.
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version 2
 *	of the License, or (at your option) any later version.
 *
 * 	Any and all changes to the program code must be documented with
 *  date, author name and e-mail, and a short description.
 *
 *	This program 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 General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package cx.warp.scout.file;

import cx.warp.scout.*;
import cx.warp.scout.lookup.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import javax.servlet.http.*;

/** The master DataGate for an EasyScout file-based implementation.  This class
		is not serialized to disk, but simply manages troop objects during runtime. */
public class FileDataGate implements cx.warp.scout.DataGate {
	
	public static String DATA_DIR = null; // DATA directory
	public static final String DES_FILENAME = "des.key";

	/* cache for the recently used troops */
	TimedHashtable recent = new TimedHashtable();
	
	/** Cache for saving troops */
	static SavingCache cache = null;
	
	/** Root password */
	private String rootPass = null;

	/** Initialization -- called upon servlet creation */
	public synchronized void init() throws DataException {
		String key = null;
		try {
			DATA_DIR = XMLLookup.directory("Data");
			
			// create the data directory if necessary
			File dir = new File(DATA_DIR);
			if (!dir.exists()) {
				dir.mkdir();
			}//if
			
			// get the des key, which resides in the first line of the des.key file
			BufferedReader in = new BufferedReader(new FileReader(new File(dir, DES_FILENAME)));
		  key = in.readLine();
			// the root password resides in the second line
			rootPass = in.readLine();
			
		}catch(Exception e) {
			throw new DataException("Could not create the data directory.", e);
		}//try
		
		// ensure the cache is created
		if (cache == null) {
			cache = new SavingCache();
			cache.setKey(key);
		}//if
	}//init
	
	/** Informs a DataGate that a Troop is in use (for caching purposes) */
	public synchronized void cacheTroop(Troop troop) throws DataException {
		String name = troop.getName().toLowerCase();
		if (recent.get(name) == null) {
			recent.put(name, troop); // save in the cache
		}//if
	}//cacheTroop
	
	/** Returns the saving cache */
	public SavingCache getSavingCache() {
		return cache;
	}//getSavingCache
	
	/** Creates a new troop, returning a reference to the new troop */
	public Troop createTroop(String name, String password) throws DataException {
		Troop troop = null;
		try {
			troop = new FileTroop(name, password);
			save(troop);
			cacheTroop(troop);
		}catch (Exception e) {
			throw new DataException("An unknown error occurred while creating the new troop.", e);
		}//try
		return troop;
	}//createTroop	
 
	/** Returns the given troop, or null if this troop does not exist */
	public synchronized Troop getTroop(String name, java.io.PrintWriter out) throws DataException {
		try {
			// move to lowercase
			name = name.toLowerCase();
		
			// first check the recent hashtable
			Troop troop = (Troop)recent.get(name);

			// get from the database/file if not found in the hashtable
			if (troop == null) {
				try {
					troop = cache.getTroop(name);
					cacheTroop(troop);
				}catch (Exception e) {
//out.println("<pre>");
//e.printStackTrace(out);
//out.println("</pre>");
					// do nothing, the troop didn't exist
				}//try
			}//if
		
			return troop;
		}catch(Exception e) {
			throw new DataException("Could not access troop data files.", e);
		}//try
	}//getTroop
	
	/** Saves a troop object */
	public static synchronized void save(Troop troop) throws DataException {
		try {
			cache.addTroop(troop);
		}catch(Exception e) {
			throw new DataException("Could not save troop file.", e);
		}//try
	}//save

	/** Prints client information */
	public void printClients(HttpServletRequest request, PrintWriter out, Session session) throws DataException {
		out.println("<table border=1 cellspacing=0 cellpadding=0 width=100%>");
		out.println("<tr>");
		out.println("<th>" + Utils.font() + "&nbsp;</th>");
		out.println("<th>" + Utils.font() + "Troop</th>");
		out.println("<th>" + Utils.font() + "File Size</th>");
		out.println("<th>" + Utils.font() + "Last Access</th>");
		out.println("</tr>");
		File dir = new File(DATA_DIR);
		File files[] = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			if (i % 25 == 24) {
				out.println("</table><table border=1 cellspacing=0 cellpadding=0 width=100%>");
			}//if
			try {
				out.println("<tr>");
				out.println("<td>" + Utils.font() + String.valueOf(i + 1) + ".</td>");
				out.println("<td>" + Utils.font());
				out.println("<a target=_blank href=\"" + Utils.servletdir() +
				            "?z=" + session.getZ() +
										"&action=Login" +
										"&troop=" + Utils.replace(files[i].getName(), " ", "%20") +
			              "\">" + files[i].getName() + "</a>");
			  out.println("</td>");
				out.println("<td>" + Utils.font() + String.valueOf(files[i].length() / 1024) + "K</td>");
				out.println("<td>" + Utils.font() + Utils.format(new Date(files[i].lastModified())) + "</td>");
				out.println("</tr>");
			}catch (Exception e) {
				e.printStackTrace();
			}//try
		}//for i
		out.println("</table>");
	}//printClients

	/** Validates the root password */
	public boolean validateRoot(String password) {
		if (rootPass != null && rootPass.equals(password)) {
			return true;
		}//if
		return false;
	}//validateRoot

}//class FileDataGate
