/***********************************************************************
 * 
 *  Copyright (C) 2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 *  Author: Juan Carlos Luciani <jluciani@novell.com>
 *  
 ***********************************************************************/

package InitConfigFile;

import java.io.*;
import java.util.*;

/**
 * Summary description for Program
 */
public class Program
{
	final static int ERROR_NO_ERROR						= 0;
	final static int ERROR_INVALID_NUMBER_OF_PARAMS		= -1;
	final static int ERROR_MISSING_TEMPLATE				= -3;
	final static int ERROR_MISSING_TEMPLATE_FILE		= -8;
	final static int ERROR_OUTPUT_PROPERTY_MISSING		= -9;
	final static int ERROR_OUTPUT_COPY_FAILED			= -12;
	final static int ERROR_IO_EXCEPTION					= -13;
	final static int ERROR_MISSING_PROPERTIES			= -15;
	final static int ERROR_UNABLE_TO_READ_PROPERTIES	= -16;
	final static int ERROR_PROPERTIES_FILE_IS_EMPTY		= -17;
	final static int ERROR_MISSING_INSTALL_DIR			= -18;
	final static int ERROR_INSTALL_DIR_NOT_A_DIR		= -19;
	final static int ERROR_BAD_INSTALL_DIR_PARAM		= -20;
	final static int ERROR_BAD_PROPERTY_FILE_PARAM		= -21;
	final static int ERROR_MISSING_PROPERTIES_FILE		= -22;
	final static int ERROR_MISSING_INSTALL_DIR_PARAM	= -23;
	final static int ERROR_MISSING_PROPERTY_FILE_PARAM	= -24;
	final static int ERROR_BAD_TEMPLATE_FILE_PARAM		= -25;
	final static int ERROR_BAD_OUTPUT_FILE_PARAM		= -26;
	final static int ERROR_MISSING_TEMPLATE_FILE_PARAM	= -27;
	final static int ERROR_MISSING_OUTPUT_FILE_PARAM	= -28;
	final static int ERROR_BAD_PROPERTY_PARAM			= -29;

	final static String TEMPLATE_FILE_PARAM		= "template=";
	final static String OUTPUT_FILE_PARAM		= "output=";
	final static String INSTALL_DIR_PARAM		= "ATS_INSTALL_DIR=";
	final static String INSTALL_DIR_PROPERTY	= "ATS_INSTALL_DIR";
	final static String PROPERTY_FILE_PARAM		= "propertyfile=";

	Properties		properties;
	File			fileProperties;
	FileInputStream	fisProperties;
	File			fileTemplate;
	File			fileOutput;
	File			file;
	FileWriter		fw;
	String[]		rgsSearchFor;
	String[]		rgsReplaceWith;
	String			sInstallDir;
	String			sTemplate;
	String			sOutput;

	public static void main(String[] args)
	{
		Program p = new Program(args);
	}

	Program(String[] args)
	{
		int rc = ERROR_NO_ERROR;

		properties = new Properties();
		fileProperties = null;
		fisProperties = null;
		fileTemplate = null;
		fileOutput = null;

		try
		{
			file = new File("c:\\test.log");
			fw = new FileWriter(file);

			log("Here we go: " + args.length);
			for (int i = 0; i < args.length; i++)
			{
				log("Arg " + i + " = " + args[i]);
			}

			// Process the arguments
			if (ERROR_NO_ERROR == (rc = processArgs(args)))
			{
				// Process the properties
				if (ERROR_NO_ERROR == (rc = processProperties()))
				{
					rc = createOutputFile();
				}
			}

		}
		catch (IOException e)
		{
			rc = ERROR_IO_EXCEPTION;
		}
		finally
		{
			try
			{
				log("return code = " + rc);
				fw.flush();
				fw.close();
			}
			catch (Exception e1)
			{
			}
		}
		System.exit(rc);
	}

	int processArgs(String[] args)
	{
		String sProperties;
		File fileInstallDir = null;
		int i;
		int iEquals;
		String sKey;
		String sValue;

		// Validate the number of parameters
		if (args.length < 3)
		{
			return ERROR_INVALID_NUMBER_OF_PARAMS;
		}

		for (i = 0; i < args.length; i++)
		{
			log("arg[" + i + "] = " +args[i]);

			// is this the install dir param?
			if (args[i].startsWith(INSTALL_DIR_PARAM))
			{
				// Make sure it is more the the param tag
				if (args[i].length() <= INSTALL_DIR_PARAM.length())
				{
					return ERROR_BAD_INSTALL_DIR_PARAM;
				}

				sInstallDir = args[i].substring(INSTALL_DIR_PARAM.length()).trim();
				fileInstallDir = new File(sInstallDir);

				// Make sure the install dir can be found
				if (!fileInstallDir.exists())
				{
					return ERROR_MISSING_INSTALL_DIR;
				}

				// Make sure the install dir is a directory
				if (!fileInstallDir.isDirectory())
				{
					return ERROR_INSTALL_DIR_NOT_A_DIR;
				}

				properties.setProperty(INSTALL_DIR_PROPERTY, sInstallDir);
			}

			// is this the properties file param?
			else if (args[i].startsWith(PROPERTY_FILE_PARAM))
			{
				// Make sure it is more than the param tag
				if (args[i].length() <= PROPERTY_FILE_PARAM.length())
				{
					return ERROR_BAD_PROPERTY_FILE_PARAM;
				}

				sProperties = args[i].substring(PROPERTY_FILE_PARAM.length()).trim();
				fileProperties = new File(sProperties);

				// Make sure the properties file can be found
				if (!fileProperties.exists())
				{
					return ERROR_MISSING_PROPERTIES_FILE;
				}

				// Read the properties
				try
				{
					fisProperties = new FileInputStream(fileProperties);
					properties.load(fisProperties);
				}
				catch (IOException ioe)
				{
					return ERROR_UNABLE_TO_READ_PROPERTIES;
				}
			}

			else if (args[i].startsWith(TEMPLATE_FILE_PARAM))
			{
				// Make sure it is more than the param tag
				if (args[i].length() <= TEMPLATE_FILE_PARAM.length())
				{
					return ERROR_BAD_TEMPLATE_FILE_PARAM;
				}

				sTemplate = args[i].substring(TEMPLATE_FILE_PARAM.length()).trim();
				fileTemplate = new File(sTemplate);

				// Make sure the template file can be found
				if (!fileTemplate.exists())
				{
					log(ERROR_MISSING_TEMPLATE_FILE, sTemplate);
					return ERROR_MISSING_TEMPLATE_FILE;
				}
			}

			else if (args[i].startsWith(OUTPUT_FILE_PARAM))
			{
				// Make sure it is more than the param tag
				if (args[i].length() <= OUTPUT_FILE_PARAM.length())
				{
					return ERROR_BAD_OUTPUT_FILE_PARAM;
				}

				sOutput = args[i].substring(OUTPUT_FILE_PARAM.length()).trim();
				fileOutput = new File(sOutput);
			}

			// Handle additional parameters
			else
			{
				if (-1 == (iEquals = args[i].indexOf("=")) ||
					0 == iEquals ||
					args[i].length() == iEquals)
				{
					return ERROR_BAD_PROPERTY_PARAM;
				}
				sKey = args[i].substring(0, iEquals);
				sValue = args[i].substring(iEquals + 1);
				properties.setProperty(sKey, sValue);
			}
		}

		// Make sure we got an install dir
		if (null == fileInstallDir)
		{
			return ERROR_MISSING_INSTALL_DIR_PARAM;
		}

		// Make sure we got a template file
		if (null == fileTemplate)
		{
			return ERROR_MISSING_TEMPLATE_FILE_PARAM;
		}

		// Make sure we got an output file
		if (null == fileOutput)
		{
			return ERROR_MISSING_OUTPUT_FILE_PARAM;
		}

		// Note: the properties file parameter is optional

		return ERROR_NO_ERROR;
	}

	int processProperties()
	{
		try
		{
			Enumeration e;
			String sKey;
			String sValue;
			int i = 0;

			e = properties.propertyNames();

			rgsSearchFor = new String[properties.size()];
			rgsReplaceWith = new String[properties.size()];

			while (e.hasMoreElements())
			{
				sKey = (String)e.nextElement();
				sValue = (String)properties.get(sKey);

				log("Property key = " + sKey + "  Value = " + sValue);

				rgsSearchFor[i] = sKey;
				rgsReplaceWith[i] = sValue;
				i++;
			}
		}
		catch (Exception ex1)
		{
			return -111;
		}

		return ERROR_NO_ERROR;
	}

	int createOutputFile()
	{
		LineNumberReader lnr = null;
		FileWriter fwOutput = null;
		String sLineTemplate;
		String sLineOutput;
		int iSearchFor;
		int i;

		try
		{
			// Open the files
			lnr = new LineNumberReader(new FileReader(fileTemplate));
		}
		catch (Exception e)
		{
			return -40;
		}

		try
		{
			fwOutput = new FileWriter(fileOutput);
		}
		catch (Exception e)
		{
			return -41;
		}
		try
		{
			// For each line of text in the template file...
			while (null != (sLineTemplate = lnr.readLine()))
			{
				sLineOutput = sLineTemplate;
				log("<-- " + sLineOutput);

				// For each term to be replaced...
				for (i = 0; i < rgsSearchFor.length; i++)
				{
					log("searching for " + rgsSearchFor[i]);
					// Replace all instances of the term on the line
					while (-1 != (iSearchFor = sLineOutput.indexOf(rgsSearchFor[i])))
					{
						log("replacing " + rgsSearchFor[i] + " at position " + iSearchFor + " with " + rgsReplaceWith[i]);
						sLineOutput = sLineOutput.substring(0, iSearchFor) + rgsReplaceWith[i] +
								sLineOutput.substring(iSearchFor + rgsSearchFor[i].length());
					}
				}
				try
				{
					fwOutput.write(sLineOutput + "\r\n");
					log("--> " + sLineOutput);
				}
				catch (Exception e)
				{
					return -42;
				}
			}

			// Clean up
			fwOutput.flush();
			fwOutput.close();
			lnr.close();
		}
		catch (Exception e)
		{
			return ERROR_OUTPUT_COPY_FAILED;
		}
		return ERROR_NO_ERROR;
	}

	void log(int err)
	{
		log(err, null);
	}

	void log(int err, String s)
	{
		String sMessage = "";

		switch (err)
		{
			case ERROR_NO_ERROR:
				sMessage = "No error";
				break;
			case ERROR_INVALID_NUMBER_OF_PARAMS:
				sMessage = "Invalid number of parameters: 4 expected";
				break;
			case ERROR_MISSING_TEMPLATE:
				sMessage = "Template file not found";
				break;
//			case ERROR_TEMPLATE_PROPERTY_MISSING:
//				sMessage = "Template file parameter missing";
//				break;
			case ERROR_OUTPUT_PROPERTY_MISSING:
				sMessage = "Output file parameter missing";
				break;
			case ERROR_OUTPUT_COPY_FAILED:
				sMessage = "Unable to create output file";
				break;
			case ERROR_IO_EXCEPTION:
				sMessage = "IOException";
				break;
			case ERROR_MISSING_PROPERTIES:
				sMessage = "Properties file not found";
				break;
			case ERROR_UNABLE_TO_READ_PROPERTIES:
				sMessage = "Unable to read properties file";
				break;
			default:
				sMessage = "Unknown error: " + err;
				break;
		}

		if (null != s)
		{
			sMessage = sMessage + s;
		}
		log(sMessage);
	}

	void log(String s)
	{
		try
		{
			fw.write(this.getClass().getName() + ": " + s + "\r\n");
		}
		catch (IOException ioe)
		{
		}
	}
}