package org.biomoby.registry.rdfagent.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;

import org.biomoby.registry.properties.MobyProperties;

/*
 * the following line belongs in the /usr/local/apache2/conf/mobycentral.config file
 * rdfagent=/export/home/nina/rdfagent/run-RDFagent
 * 
 */
//import ca.icapture.moby.util.Log;
/**
 * A class that retrieves the constants located in
 * RDFagent.home/RDFagent_config.txt
 * <p>
 * 
 * @author Nina Opushneva
 * @author Edward Kawas
 * 
 * 
 */

public class Constants {

	/*
	 * the property key that is used to get the agents home directory
	 */
	private final static String AGENT_HOME = "RDFagent.home";

	/**
	 * The config_file name.
	 */
	public final static String CONFIG_FILE = "RDFagent_config.txt";

	/**
	 * The agents home directory.
	 */
	public static String RDFagentHome;

	/**
	 * The name of the registry's administrator.
	 */
	public static String ADMIN_NAME = null;

	/**
	 * The email address of the registry's administrator.
	 */
	public static String ADMIN_EMAIL = null;

	/**
	 * The url for the registry.
	 */
	public static String REGISTRY_URL = null;

	/**
	 * The registry's endpoint.
	 */
	public static String REGISTRY_URI = null;

	/**
	 * The location of the mobycentral.conf file.
	 */
	public static String REGISTRY_CONF_FILE = null;

	/**
	 * Should the agent ignore null signature urls? Defaults to false.
	 */
	public static boolean REGISTRY_IGNORE_NULL = false;

	//public static boolean DUMP_SERVICE_LIST = false;

	/**
	 * The passphrase that enables the agent to deregister from mobycentral.
	 */
	public static String REGISTRY_KEYPHRASE = null;

	/**
	 * Should the agent try to email using smtp? Defaults to false.
	 */
	public static boolean SMTP_ENABLE = false;

	/**
	 * The address of the smtp server.
	 */
	public static String SMTP_SERVER = null;

	/**
	 * The smtp login.
	 */
	public static String SMTP_LOGIN = null;

	/**
	 * The smtp password.
	 */
	public static String SMTP_PSWD = null;

	/**
	 * Should the agent log? Defaults to true.
	 */
	public static boolean LOG_ENABLE = true;

	/**
	 * The level of logging. Defaults to info logging.
	 */
	public static Level LOG_LEVEL = null;

	/**
	 * Should the agent deregister services? Defaults to false.
	 */
	public static boolean REGISTRY_ENABLE_DEREGISTER = false;
	
	/**
	 * Should the agent deregister services when invoked via registerService? Defaults to false.
	 */
	public static boolean REGISTRY_ENABLE_DEREGISTER_FROM_URL = false;

	/**
	 * Does the agent perform updates on modified services?
	 */
	public static boolean REGISTRY_ENABLE_SERVICE_UPDATES = false;

	/**
	 * How many chances does a service get before deregistration? Defaults to 3.
	 */
	public static int REGISTRY_DEREGISTER_COUNT = 3;

	/**
	 * Should the agent email service providers with changes to their services?
	 * Defaults to true.
	 */
	public static boolean REGISTRY_EMAIL = true;

	/**
	 * The directory in which to place logs.
	 */
	public static String LOGFILE_PATH = null;

	/**
	 * The directory in which to place reports.
	 */

	/**
	 * The Central Admin endpoint for service removal
	 */
	public static String REGISTRY_REMOVAL_ENDPOINT = null;

	/**
	 * The Central Admin uri for service removal
	 */
	public static String REGISTRY_REMOVAL_URI = null;

	/**
	 * The username to access the password protected Central Admin dispatcher
	 */
	public static String REGISTRY_REMOVAL_USERNAME = null;

	/**
	 * The password associated with the username
	 */
	public static String REGISTRY_REMOVAL_PASSWORD = null;

	static {
		RDFagentHome = System.getProperty(AGENT_HOME);
		if (RDFagentHome == null || RDFagentHome.equals("")) {
			System.err
					.println("The property 'RDFagent.home' was not specified at runtime. "
							+ System.getProperty("line.separator")
							+ "Please ensure that you specify this property. "
							+ System.getProperty("line.separator")
							+ "If you do not know how to continue, please contact the Moby mailing list.");
			System.exit(1);
		}
		if (!RDFagentHome.endsWith("/") || !RDFagentHome.endsWith("\\")
				|| !RDFagentHome.endsWith(System.getProperty("file.separator"))) {
			RDFagentHome = RDFagentHome + System.getProperty("file.separator");
		}
		String str = RDFagentHome + CONFIG_FILE;
		Properties prop = new Properties();
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(str);
		} catch (FileNotFoundException e) {
			System.err
					.println("The config file @ "
							+ str
							+ " was not found. Please ensure that it is placed where you said it would be."
							+ System.getProperty("line.separator")
							+ "Full message:"
							+ System.getProperty("line.separator")
							+ e.getLocalizedMessage());
			System.exit(1);

		}

		try {
			prop.load(fis);
		} catch (IOException e) {
			System.err.println("The config file @ " + str
					+ " caused an I/O error. Please try again. "
					+ System.getProperty("line.separator") + "Full message:"
					+ System.getProperty("line.separator")
					+ e.getLocalizedMessage());
			System.exit(1);
		} catch (IllegalArgumentException e) {
			System.err
					.println("The config file @ "
							+ str
							+ " contained a malformed Unicode escape sequence. Please try again. "
							+ System.getProperty("line.separator")
							+ "Full message:"
							+ System.getProperty("line.separator")
							+ e.getLocalizedMessage());
			System.exit(1);
		}

		// start setting the configuration
		ADMIN_NAME = prop.getProperty("admin.name");

		ADMIN_EMAIL = prop.getProperty("admin.email");

		REGISTRY_URL = prop.getProperty("admin.registry.url");

		REGISTRY_URI = prop.getProperty("admin.registry.uri");

		REGISTRY_CONF_FILE = prop.getProperty("admin.registry.conf");

		REGISTRY_IGNORE_NULL = extractBoolean(prop
				.getProperty("admin.registry.ignore.null"));

		REGISTRY_KEYPHRASE = prop
				.getProperty("admin.registry.removal.keyphrase");

		SMTP_ENABLE = extractBoolean(prop.getProperty("admin.mail.smtp.enable"));

		SMTP_SERVER = prop.getProperty("admin.mail.smtp.server");

		SMTP_LOGIN = prop.getProperty("admin.mail.smtp.login");

		SMTP_PSWD = prop.getProperty("admin.mail.smtp.password");

		LOG_ENABLE = extractBoolean(prop.getProperty("log.enable"));

		LOG_LEVEL = extractLogLevel(prop.getProperty("log.level"));

		REGISTRY_ENABLE_DEREGISTER = extractBoolean(prop
				.getProperty("registry.deregister"));
		
		REGISTRY_ENABLE_DEREGISTER_FROM_URL = extractBoolean(prop
				.getProperty("registry.deregister.from_url"));

		REGISTRY_ENABLE_SERVICE_UPDATES = extractBoolean(prop
				.getProperty("registry.update.services"));
		
		REGISTRY_DEREGISTER_COUNT = extractInt(prop
				.getProperty("registry.count"));

		REGISTRY_EMAIL = extractBoolean(prop
				.getProperty("registry.email"));

		LOGFILE_PATH = prop.getProperty("agent.log.directory");

		REGISTRY_REMOVAL_ENDPOINT = prop
				.getProperty("admin.registry.removal.endpoint");
		REGISTRY_REMOVAL_URI = prop.getProperty("admin.registry.removal.uri");
		REGISTRY_REMOVAL_USERNAME = prop
				.getProperty("admin.registry.removal.username");
		REGISTRY_REMOVAL_PASSWORD = prop
				.getProperty("admin.registry.removal.password");

		if (LOGFILE_PATH == null) {
			LOGFILE_PATH = RDFagentHome + "logs/";
		}
		// append a file separator to the directory if needed
		if (!LOGFILE_PATH.endsWith("/") || !LOGFILE_PATH.endsWith("\\")
				|| !LOGFILE_PATH.endsWith(System.getProperty("file.separator"))) {
			LOGFILE_PATH = LOGFILE_PATH + System.getProperty("file.separator");
		}
		// create the directory if need be
		File dir = new File(LOGFILE_PATH);
		if (!dir.exists())
			dir.mkdirs();
		if (!dir.canWrite()) {
			System.err
					.println("Agent cannot write to the directory: "
							+ dir.getAbsolutePath()
							+ "."
							+ System.getProperty("line.separator")
							+ "Please set up the appropriate permissions for that directory.");
			System.exit(1);
		}

		// now do some null checking for the variables

		if (REGISTRY_ENABLE_DEREGISTER || !REGISTRY_IGNORE_NULL || REGISTRY_ENABLE_DEREGISTER_FROM_URL) {
			// since deregistration is enabled, make sure that properties
			// associated with deregistering are not null
			if (REGISTRY_KEYPHRASE == null) {
				System.err
						.println("The keyphrase was missing from the config file."
								+ System.getProperty("line.separator")
								+ "This phrase is important for service deregistration.");
				System.exit(1);
			}
			if (REGISTRY_REMOVAL_ENDPOINT == null
					|| REGISTRY_REMOVAL_ENDPOINT.trim().equals("")) {
				System.err
						.println("The endpoint for Central Admin was missing from the config file."
								+ System.getProperty("line.separator")
								+ "This endpoint is necessary for service deregistration.");
				System.exit(1);
			}
			if (REGISTRY_REMOVAL_URI == null
					|| REGISTRY_REMOVAL_URI.trim().equals("")) {
				System.err
						.println("The URI for Central Admin was missing from the config file."
								+ System.getProperty("line.separator")
								+ "This URI is necessary for service deregistration.");
				System.exit(1);
			}
			if (REGISTRY_REMOVAL_PASSWORD == null) {
				System.err
						.println("The password for access to Central Admin was missing from the config file."
								+ System.getProperty("line.separator")
								+ "This password is necessary for service deregistration.");
				System.exit(1);
			}
			if (REGISTRY_REMOVAL_USERNAME == null) {
				System.err
						.println("The username for access to Central Admin was missing from the config file."
								+ System.getProperty("line.separator")
								+ "This username is necessary for service deregistration.");
				System.exit(1);
			}
		}

		if (REGISTRY_CONF_FILE == null || REGISTRY_CONF_FILE.trim().equals("")
				|| REGISTRY_URL == null || REGISTRY_URL.trim().equals("")
				|| REGISTRY_URI == null || REGISTRY_URI.trim().equals("")) {
			// try and get these from the o/s environment
			Properties p = MobyProperties.PROPERTIES();
			if (p.getProperty("MOBY_CENTRAL_CONFIG") != null) {
				REGISTRY_CONF_FILE = p.getProperty("MOBY_CENTRAL_CONFIG");

			} else {
				System.err
						.println("The property specifying the location of the mobycentral.config file is missing."
								+ System.getProperty("line.separator")
								+ "Please fix this in the configuration file.");
				System.exit(1);
			}
			if (p.getProperty("MOBY_SERVER") != null) {
				REGISTRY_URL = p.getProperty("MOBY_SERVER");
			} else {
				System.err
						.println("The property specifying the mobycentral server url for your registry is missing."
								+ System.getProperty("line.separator")
								+ "Please fix this in the configuration file.");
				System.exit(1);
			}
			if (p.getProperty("MOBY_URI") != null) {
				REGISTRY_URI = p.getProperty("MOBY_URI");

			} else {
				System.err
						.println("The property specifying the mobycentral endpoint for your registry is missing."
								+ System.getProperty("line.separator")
								+ "Please fix this in the configuration file.");
				System.exit(1);
			}

		}
		// set the URI,URL and conf file location in the system properties for
		// later use by other jMoby code

		System.setProperty("MOBY_URI", REGISTRY_URI);
		System.setProperty("MOBY_CENTRAL_CONFIG", REGISTRY_CONF_FILE);
		System.setProperty("MOBY_SERVER", REGISTRY_URL);
		// if we are emailing, admin name and email cannot be null
		if (REGISTRY_EMAIL ) {

			if (SMTP_ENABLE) {
				// since smtp mail is enabled, make sure that properties
				// associated with mailing are not null
				if (SMTP_SERVER == null || SMTP_SERVER.trim().equals("")) {
					System.err
							.println("The SMTP server address is missing in the config file."
									+ System.getProperty("line.separator")
									+ "Please fix this in the configuration file or disable SMTP mailing.");
					System.exit(1);
				}
				if (SMTP_LOGIN == null) {
					SMTP_LOGIN = "";
					System.err
							.println("No SMTP login information found in config file. Using '' as the login.");
				}
				if (SMTP_PSWD == null) {
					SMTP_PSWD = "";
					System.err
							.println("No SMTP password found in config file. Using '' as the password.");
				}
			}

			if (ADMIN_EMAIL == null || ADMIN_EMAIL.trim().equals("")) {
				System.err
						.println("The mobycentral registry administrator's email address was missing from the config file."
								+ System.getProperty("line.separator")
								+ "Please fix this in the configuration file.");
				System.exit(1);
			}
			if (ADMIN_NAME == null || ADMIN_NAME.trim().equals("")) {
				System.err
						.println("The mobycentral registry administrator's name was missing from the config file."
								+ System.getProperty("line.separator")
								+ "Please fix this in the configuration file.");
				System.exit(1);
			}
		}
	}

	private static boolean extractBoolean(String bool) {
		if (bool == null) {
			System.err
					.println("An empty value was found where a yes or no was expected in the config file."
							+ System.getProperty("line.separator")
							+ "  Please ensure that all values in the config file are entered correctly.");
			System.exit(1);
		}
		bool = bool.trim();
		if (bool.equalsIgnoreCase("yes") || bool.equalsIgnoreCase("true")
				|| bool.equalsIgnoreCase("1"))
			return true;
		return false;

	}

	private static int extractInt(String integer) {
		if (integer == null) {
			System.err
					.println("An empty value was found where an integer was expected in the config file."
							+ System.getProperty("line.separator")
							+ "  Please ensure that all values in the config file are entered correctly.");
			System.exit(1);
		}
		integer = integer.trim();
		int count = 3;
		try {
			count = Integer.parseInt(integer);
		} catch (NumberFormatException e) {
			System.err
					.println("Invalid count specified as a property with key: registry.count."
							+ System.getProperty("line.separator")
							+ "Defaulting to 3.");
		}

		return count;

	}

	private static Level extractLogLevel(String level) {
		if (level == null) {
			System.err
					.println("An empty value was found where an info, warn or severe was expected in the config file."
							+ System.getProperty("line.separator")
							+ "  Please ensure that all values in the config file are entered correctly.");
			System.exit(1);
		}
		level = level.trim();
		if (level.equalsIgnoreCase("info")) {
			return Log.INFO;
		}
		if (level.equalsIgnoreCase("all")) {
			return Log.ALL;
		}

		if (level.equalsIgnoreCase("warn")) {
			return Log.WARN;
		}
		if (level.equalsIgnoreCase("severe")) {
			return Log.SEVERE;
		}
		// default to all logging
		return Log.INFO;
	}
}
