package com.interpress_project.modernshare.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.commons.io.FilenameUtils;

import com.interpress_project.modernshare.AppKeys;
import com.interpress_project.modernshare.ipcommon.SystemBase;
import com.interpress_project.modernshare.serveradm.exceptions.NoSVNInstalledException;

/**
 * Represents a singleton.
 * @stereotype Singleton Factory
 */
public class PropertyManager {
	private final SystemBase sb = SystemBase.getInstance();
	private File propfile = null;
	private Properties prop = null;
	/**
	 * Holds singleton instance
	 */
	private static PropertyManager instance;

	/**
	 * PropertyManager
	 */
	protected PropertyManager() {
		prop = new Properties();
	}

	/**
	 * initialize
	 * @param filename
	 */
	public void initialize(String filename) {
		propfile = new File(FilenameUtils.normalize(filename));

		load();

		sb.getLogger().info("HotShot server properties located in " + propfile.getAbsolutePath());
		sb.getLogger().info("Administartor account : " + getAdministratorAccount());
		sb.getLogger().info("Administrator name : " + getAdministrator());
		sb.getLogger().info("Administrator mail : " + getAdministratorEmail());
		sb.getLogger().info("HotShot directory : " + sb.getCurrentDirectory());
		sb.getLogger().info("Repository directory : " + getSVNRootdir());
		sb.getLogger().info("Repository backup directory : " + getSVNBackupdir());
		try {
			sb.getLogger().info("SVN system directory : " + getSVNHome());
		}
		catch (NoSVNInstalledException e) {
		}
	}

	/**
	 * load
	 */
	private void load() {
		sb.getLogger().debug("Enter load().");

		try {
			prop.load(new FileInputStream(propfile));
		}
		catch (FileNotFoundException ex) {
			sb.getLogger().error("Property file " + propfile.getAbsolutePath() + " not found. Server is forcely terminated.",
			  ex);
			System.exit(-1);
		}
		catch (IOException ex) {
			sb.getLogger().fatal("IOException loading properties. Server is forcely terminated.", ex);
			System.exit(-1);
		}
		sb.getLogger().debug("Leave load().");
	}

	/**
	 * save
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void save() throws FileNotFoundException, IOException {
		prop.store(new FileOutputStream(AppKeys.ServerPropFilename), "Properties for HotShot server.");
	}

	/**
	 * getAdminport
	 * @return
	 */
	public String getAdminport() {
		return prop.getProperty(AppKeys.ADMIN_PORT, "17770");
	}

	/**
	 * getAdministrator
	 * @return
	 */
	public String getAdministrator() {
		return prop.getProperty(AppKeys.ADMINISTRATOR, "unknown");
	}

	/**
	 * getAdministartorEmail
	 * @return
	 */
	public String getAdministratorEmail() {
		return prop.getProperty(AppKeys.ADMINISTRATOR_EMAIL, "unknown@unknown.com");
	}

	/**
	 * getAdministratorAccount
	 * @return
	 */
	public String getAdministratorAccount() {
		return prop.getProperty(AppKeys.ADMIN_ACCOUNT, "root");
	}

	/**
	 * getAdministratorPassword
	 * @return
	 */
	public String getAdministratorPassword() {
		return prop.getProperty(AppKeys.ADMIN_PASSWORD, "masterkey");
	}

	/**
	 * getSVNHome
	 * @return
	 * @throws NoSVNInstalledException
	 */
	public String getSVNHome() throws NoSVNInstalledException {
		String homepath = prop.getProperty(AppKeys.SVN_HOME, "./svn");
		File file = new File(FilenameUtils.normalize(homepath));
		if (file.isDirectory()) {
			return file.getAbsolutePath();
		}
		String msg = "Couldn't find out SubVersion system directory: " + file.getAbsolutePath() + "\n"
		    + "Please specify the svn directory with " + AppKeys.SVN_HOME + " in " + propfile;

		throw new NoSVNInstalledException(msg);
	}

	/**
	 * getSVNAdminCommand
	 * @return
	 * @throws NoSVNInstalledException
	 */
	public String getSVNAdminCommand() throws NoSVNInstalledException {
		String homepath = getSVNHome();
		homepath = homepath + "/bin/" + "svnadmin";
		File file = new File(FilenameUtils.normalize(homepath));
		return file.getAbsolutePath();
	}

	/**
	 * getSVNServerThreadMinimum
	 * @return
	 */
	public int getSVNServerThreadMinimum() {
		String min = prop.getProperty(AppKeys.SVN_POOLMIN, "16");
		return Integer.parseInt(min);
	}

	/**
	 * getSVNServerThreadMaximum
	 * @return
	 */
	public int getSVNServerThreadMaximum() {
		String max = prop.getProperty(AppKeys.SVN_POOLMAX, "64");
		return Integer.parseInt(max);
	}

	/**
	 * getServerName
	 */
	public String getServerName() {
		String hostname = "localhost";
		try {
			InetAddress addr = InetAddress.getLocalHost();
			hostname = addr.getHostName();
		}
		catch (UnknownHostException ex) {
		}
		String host = prop.getProperty(AppKeys.ADMIN_HOST, hostname);
		return host;
	}

	/**
	 * getVirtualServerName
	 * @return
	 */
	public String getVirtualServerName() {
		String hostname = prop.getProperty(AppKeys.ADMIN_VIRTUALHOST, getServerName());
		return hostname.trim();
	}

	/**
	 * getSVNServerPort
	 * @return
	 */
	public int getSVNServerPort() {
		String port = prop.getProperty(AppKeys.SVN_PORT, "3690");
		return Integer.parseInt(port.trim());
	}

	/**
	 * getSVNRootdir
	 * @return
	 */
	public String getSVNRootdir() {
		String p = prop.getProperty(AppKeys.SVN_ROOTDIR, "./hotshot_repository.d");
		File f = new File(FilenameUtils.normalize(p));
		return f.getAbsolutePath();
	}

	/**
	 * getSVNBackupdir
	 * @return
	 */
	public String getSVNBackupdir() {
		String p = prop.getProperty(AppKeys.SVN_BACKUPDIR, "./hotshot_repository_backup.d");
		File f = new File(FilenameUtils.normalize(p));
		return f.getAbsolutePath();
	}

	/**
	 * hasBdbused
	 * @return
	 */
	public boolean hasBdbused() {
		String type = prop.getProperty(AppKeys.SVN_DBTYPE, "true");
		if (type.equalsIgnoreCase("true")) {
			return true;
		}
		return false;
	}

	/**
	 * getTcpBufSz
	 * @return
	 */
	public int getTcpBufSz() {
		String sz = prop.getProperty(AppKeys.SVN_TCPBUFSZ, "32768");
		return Integer.parseInt(sz);
	}

	/**
	 * getSVNServerCommand
	 * @return
	 * @throws NoSVNInstalledException
	 */
	public String getSVNServerCommand() throws NoSVNInstalledException {
		String homepath = getSVNHome();
		homepath = homepath + "/bin/" + "svnserve";
		File file = new File(FilenameUtils.normalize(homepath));
		return file.getAbsolutePath();
	}

	/**
	 * getSVNServerCommandPort
	 * @return
	 */
	public String getSVNServerCommandPort() {
		String port = prop.getProperty(AppKeys.SVN_CMDPORT, "55535");
		return port;
	}

	/**
	 * setKeystore
	 * @param s
	 */
	public void setKeystore(String s) {
		prop.setProperty(AppKeys.KEYSTORE, s);
	}

	/**
	 * getKeystore
	 * @return
	 */
	public String getKeystore() {
		return prop.getProperty(AppKeys.KEYSTORE, "jsse_server_ks");
	}

	/**
	 * setKeystorePass
	 * @param s
	 */
	public void setKeystorePass(String s) {
		prop.setProperty(AppKeys.KEYSTOREPASS, s);
	}

	/**
	 * getKeystorePass
	 * @return
	 */
	public String getKeystorePass() {
		return prop.getProperty(AppKeys.KEYSTOREPASS, "jsse_server_ks_pass");
	}

	/**
	 * getXMLDBFileName
	 * @return
	 */
	public String getXMLDBFileName() {
		String path = getSVNRootdir();
		path = path + "/" + AppKeys.XMLDBFILE;
		return FilenameUtils.normalize(path);
	}

	/**
	 * getThreadTimeout
	 * @return
	 */
	public int getThreadTimeout() {
		String s = prop.getProperty(AppKeys.THREADTIMEOUT, "180000");
		return Integer.valueOf(s);
	}

	/**
	 * Returns the singleton instance.
	 @return	the singleton instance
	 */
	static public PropertyManager getInstance() {
		if (instance == null) {
			instance = new PropertyManager();
		}
		return instance;
	}
}
