package hiro.yoshioka.sql.notes;

import hiro.yoshioka.classmanager.ClassManager;
import hiro.yoshioka.sql.engine.Request;
import hiro.yoshioka.sql.engine.SQLOperationType;
import hiro.yoshioka.sql.notes.reflect.WolfDBDirectory;
import hiro.yoshioka.sql.notes.reflect.WolfDatabase;
import hiro.yoshioka.sql.notes.reflect.WolfSession;
import hiro.yoshioka.sql.notes.reflect.WolfView;
import hiro.yoshioka.sql.params.ConnectionProperties;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.INameFamily;
import hiro.yoshioka.util.StringUtil;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class AbsNotesRunner {
	protected Log fLogger = LogFactory.getLog(getClass());
	public static String Form = "Form";
	public static String UniversalID = "UniversalID";
	public static String HttpURL = "HttpURL";
	public static String NotesURL = "NotesURL";
	String server;
	String userid;
	String password;
	boolean isFullAccess;
	private DBRoot root;
	SQLOperationType operation;
	protected Request request;

	/* Notes Class Definitions */

	// lotus.domino.Session
	WolfSession wolf_session;

	// lotus.domino.NotesThread
	Class notesThreadClass;
	Method notesThread_sinitThreadMethod;
	// lotus.domino.NotesFactory
	Class notesFactory;
	Method notesFactory_createSessionWithFullAccessMethod;
	Method notesFactory_createSessionMethod;

	// lotus.domino.RichTextItem
	Class richTextItemClass;

	ClassManager classManager;
	private boolean initializedFlg;

	public AbsNotesRunner(ClassManager manager, String server, String userid,
			String password) {
		this(manager, null, server, userid, password);
	}

	public AbsNotesRunner(ClassManager manager, ConnectionProperties properties) {
		this(manager, null, properties);
	}

	public AbsNotesRunner(ClassManager manager, Request request,
			ConnectionProperties properties) {
		this(manager, request, properties.getHost(), properties
				.getAuthenticate().user, properties.getAuthenticate().pass);

	}

	public AbsNotesRunner(ClassManager manager, Request request, String server,
			String userid, String password) {
		this.request = request;
		this.classManager = manager;
		this.server = server;
		this.userid = userid;
		this.password = password;
		this.isFullAccess = false;
	}

	public AbsNotesRunner() {
		this.isFullAccess = true;
	}

	public void initClass() throws Exception {
		notesThreadClass = classManager
				.getClassForName("lotus.domino.NotesThread");
		notesThread_sinitThreadMethod = notesThreadClass
				.getMethod("sinitThread");
		notesFactory = classManager
				.getClassForName("lotus.domino.NotesFactory");
		notesFactory_createSessionWithFullAccessMethod = notesFactory
				.getMethod("createSessionWithFullAccess");
		notesFactory_createSessionMethod = notesFactory.getMethod(
				"createSession", String.class, String.class, String.class);

		initializedFlg = true;
	}

	public static void main(java.lang.String[] args) {
		// NotesRunner sjd = new NotesRunner("localhost", "Hirotaka Yoshioka",
		// "password");
		// Thread nt = new Thread((Runnable) sjd);
		// nt.start();
	}

	public DBRoot getRoot() {
		return root;
	}

	public String getServer() {
		if (StringUtil.isEmpty(server)) {
			return "localhost";
		}
		return server;
	}

	public Object createSession() throws Exception {
		Object sessionInstance = null;
		if (isFullAccess) {
			notesThread_sinitThreadMethod.invoke(null);
			sessionInstance = notesFactory_createSessionWithFullAccessMethod
					.invoke(null);
		} else {
			if (request != null) {
				request.beginTask(String.format("createSession[%s]", userid), 1);
			}
			sessionInstance = notesFactory_createSessionMethod.invoke(null,
					getServer(), userid, password);
		}
		wolf_session = new WolfSession(classManager, sessionInstance);
		return this.wolf_session;
	}

	protected void test() throws Exception {
		if (!initializedFlg) {
			initClass();
		}
	}

	public void setOperation(SQLOperationType operation) {
		this.operation = operation;
	}

	protected WolfDatabase getDatabaseBySchema(INameFamily schema)
			throws Exception {
		String name = schema.getName();
		if (name.startsWith(StringUtil.DOUBLE_QUOTE_STRING)
				&& name.endsWith(StringUtil.DOUBLE_QUOTE_STRING)
				&& name.length() > 2) {
			name = name.substring(1, name.length() - 1);
		}
		WolfDBDirectory dir = wolf_session.getDbDirectory(null);
		WolfDatabase database = dir
				.getFirstDatabase(WolfDBDirectory.dbDirectory_database_type);

		while (database != null) {
			if (name.equals(database.getTitle())) {
				return database;
			}
			database = dir.getNextDatabase();
		}
		fLogger.fatal(String.format(" missig database[%s]", name));
		return null;
	}

	protected WolfDatabase getDatabaseByTable(INameFamily table)
			throws Exception {
		return getDatabaseBySchema(table.getParent());
	}

	protected WolfView getView(INameFamily table) throws Exception {

		WolfDBDirectory dir = wolf_session.getDbDirectory(null);
		WolfDatabase database = dir
				.getFirstDatabase(WolfDBDirectory.dbDirectory_database_type);

		String tableName = table.getProperties().getProperty("database");
		while (database != null) {
			if (tableName.equals(database.getTitle())) {
				if (!database.isOpen()) {
					database.open();
				}
				return database.getView(table.getName());
			}
			database = dir.getNextDatabase();
		}

		return null;
	}
}
