package com.interpress_project.modernshare.model;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.btree.BTree;
import jdbm.helper.StringComparator;

import com.interpress_project.modernshare.ipcommon.SystemBase;

/**
 * @stereotype Data Access Object
 */
public class UserConfigDAO {
	private final SystemBase sb = SystemBase.getInstance();
	private final PropertyManager propmgr = PropertyManager.getInstance();
	private RecordManager recman;
	private BTree btree;

	/**
	 * UserConfigDAO
	 */
	public UserConfigDAO() {
		sb.getLogger().debug("Enter UserConfigDAO()");

		Properties props = new Properties();
		String dbname = propmgr.getXMLDBFileName();

		try {
			recman = RecordManagerFactory.createRecordManager(dbname, props);

			// create or load gd (hashtable of dirs)
			long recid = recman.getNamedObject("HotShotServer");
			if (recid != 0) {
				sb.getLogger().debug("XMLDB reloading exist one");
				btree = BTree.load(recman, recid);
			}
			else {
				sb.getLogger().debug("XMLDB creating new one");
				btree = BTree.createInstance(recman, new StringComparator());
				recman.setNamedObject("HotShotServer", btree.getRecid());
			}
		}
		catch (Exception ex) {
			sb.getLogger().fatal("XMLDB must be corrupted so please re-boot HotShot Server. Server is terminated forcely.",
			  ex);
			new File(dbname + ".db").delete();
			new File(dbname + ".lg").delete();
			System.exit(-1);
		}
		sb.getLogger().debug("XMLDB opened.");
	}

	/**
	 * add
	 * @param account
	 * @param clientid
	 * @param value
	 */
	public synchronized void add(String account, String clientid, String value) {
		String key = mkkey(account, clientid);
		sb.getLogger().debug("Enter add(" + key + ")");

		try {
			btree.insert((String) key, (String) value, true);
			recman.commit();
		}
		catch (Exception ex) {
			sb.getLogger().error("XMLDB add(" + key + ") failed : " + ex.getMessage());
			try {
				recman.rollback();
			}
			catch (IOException ex2) {
			}
		}
		sb.getLogger().debug("Leave add(" + key + ")");
	}

	/**
	 * delete
	 * @param account
	 * @param clientid
	 */
	public synchronized void delete(String account, String clientid) {
		String key = mkkey(account, clientid);
		sb.getLogger().debug("Enter delete(" + key + ")");

		try {
			btree.remove((String) key);
			recman.commit();
		}
		catch (Exception ex) {
			sb.getLogger().error("XMLDB delete(" + key + ") failed : ", ex);
			try {
				recman.rollback();
			}
			catch (IOException ex2) {
			}
		}
		sb.getLogger().debug("Leave delete(" + key + ")");
	}

	/**
	 * find
	 * @param account
	 * @param clientid
	 * @return
	 */
	public String find(String account, String clientid) {
		String key = mkkey(account, clientid);
		String xmldata = null;
		sb.getLogger().debug("Enter find(" + key + ")");

		try {
			xmldata = (String) btree.find((String) key);
			if (xmldata == null) {
				sb.getLogger().debug("XML config data not found (" + key + ")");
			}
		}
		catch (Exception ex) {
			sb.getLogger().warn("XMLDB find(" + key + ") failed : ", ex);
		}
		sb.getLogger().debug("Leave find(" + key + ")");
		return xmldata;
	}

	/**
	 * mkkey
	 * @param account
	 * @param clientid
	 * @return
	 */
	private String mkkey(String account, String clientid) {
		String key = account + clientid;
		return key.toLowerCase();
	}

	/**
	 * dispose
	 */
	public void dispose() {
		if (recman != null) {
			try {
				recman.close();
				recman = null;
			}
			catch (IOException ex) {
				sb.getLogger().error("IOException closing XMLDB:", ex);
			}
		}
		sb.getLogger().debug("XMLDB closed.");
	}
}
