package hiro.yoshioka.sql.notes;

import hiro.yoshioka.classmanager.ClassManager;
import hiro.yoshioka.sdh2.ResultSetDataHolder2;
import hiro.yoshioka.sql.notes.reflect.WolfDatabase;
import hiro.yoshioka.sql.notes.reflect.WolfDocument;
import hiro.yoshioka.sql.notes.reflect.WolfDocumentCollection;
import hiro.yoshioka.sql.params.ConnectionProperties;
import hiro.yoshioka.sql.params.DBResourceCapturingFilter;
import hiro.yoshioka.sql.params.DBUserPass;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.DBSchema;
import hiro.yoshioka.sql.resource.IDBSchema;
import hiro.yoshioka.sql.resource.IDBTable;
import hiro.yoshioka.sql.resource.notes.NotesDBTable;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class NotesRunnerParentAndChildTree extends AbsNotesRunner implements
		Callable<ResultSetDataHolder2[]> {
	NotesDBTable table;
	ConnectionProperties properties;

	public NotesRunnerParentAndChildTree(ClassManager manager,
			ConnectionProperties properties, IDBTable table) {
		super(manager, properties);
		this.table = (NotesDBTable) table;
		this.properties = properties;

	}

	public static void main(java.lang.String[] args) {
		ConnectionProperties p = new ConnectionProperties();

		// dom
		p.setHost("10.0.0.100:8585");
		p.setAuthenticate(new DBUserPass("admin", "password"));

		p.setCaptureWithDDL(true);
		p.setCaptureWithColumnInfo(false);
		p.setCaptureWithViewInfo(false);

		p.setCapturingFilter(DBResourceCapturingFilter.MATCHES);
		p.addFilePathRegrex(".*hoge.*");
		ClassManager cm = new ClassManager();
		try {
			DBRoot root = new DBRoot();
			IDBSchema sc = new DBSchema(root);
			sc.setName("name");
			root.putResource(sc.getName(), sc);
			NotesDBTable tbl = new NotesDBTable(sc);
			tbl.setName("Res");
			tbl.setAlias("Res0");
			cm.add_lib(new File(
					"C:/tools/eclipse/wk/WolfSQLParser/ext_lib/NCSO.jar"));

			NotesRunnerParentAndChildTree sjd = new NotesRunnerParentAndChildTree(
					cm, p, tbl);
			ExecutorService ex = Executors.newSingleThreadExecutor();
			Future<ResultSetDataHolder2[]> future = ex.submit(sjd);
			ResultSetDataHolder2[] rdh = future.get();
			ex.shutdown();
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	@Override
	public ResultSetDataHolder2[] call() throws Exception {
		initClass();
		createSession();

		try {
			System.out.println("server =" + server);
			System.out.println("table.getName() =" + table.getName());

			return callTable();

		} finally {
			wolf_session.recycle();
		}
	}

	Map<String, Pc> allMap = new HashMap<String, Pc>();

	Pc root = new Pc();

	private void doclist2Rdh(WolfDocument doc) throws IllegalArgumentException,
			MalformedURLException, SecurityException, IllegalAccessException,
			InvocationTargetException, ClassNotFoundException,
			NoSuchMethodException {
		if (doc == null) {
			return;
		}

		int iCol = 0;

		Pc pc = new Pc();
		pc.universalID = doc.getUniversalID();
		pc.subject = doc.getItemValueString("subject").trim();
		pc.ref = doc.getItemValueString("$REF");
		pc.name = doc.getItemValueString("DisplayFromN");

		allMap.put(pc.universalID, pc);

		doc.recycle();

	}

	public ResultSetDataHolder2[] callTable() throws Exception {

		WolfDatabase database = getDatabaseByTable(table);

		System.out.println("database =" + database);
		if (!database.isOpen()) {
			database.open();
		}
		try {

			String query = null;
			if (table.hasAlias()) {
				query = String.format("Form=\"%s\"", table.getAlias());
			} else {
				query = String.format("Form=\"%s\"", table.getName());
			}

			System.out.println("query=" + query);
			WolfDocumentCollection docs = database.search(query, 20000);
			System.err.println("--------------------");
			System.out.println("result count=" + docs.getCount());
			WolfDocument doc = docs.getFirstDocument();

			doclist2Rdh(doc);
			while (doc != null) {
				doc = docs.getNextDocument();
				doclist2Rdh(doc);
			}
			for (Pc p : allMap.values()) {
				Pc parent = allMap.get(p.ref);
				if (parent == null) {
					// p.subject = p.subject;
				} else {
					parent.addChild(p);
				}
			}
			System.out.println("allMap.size=" + allMap.size());
			for (Pc p : allMap.values()) {
				if (p.hasChild() && !p.hasParent()) {
					if (root.hasChild() && root.childMap.containsKey(p.ref)) {
						Pc parent = root.getChild(p.ref);
						parent.addChild(p);
					} else {
						WolfDocument docP = database.getDocumentByUNID(p.ref);
						if (docP != null) {
							Pc pc = new Pc();
							pc.universalID = docP.getUniversalID();
							pc.subject = docP.getItemValueString("subject");
							pc.ref = docP.getItemValueString("$REF");
							docP.recycle();
							pc.addChild(p);
							root.addChild(pc);
						} else {
							System.err.println("no parent!!!!![" + p.ref + "]");
						}
					}
				}
			}
			root.dump(0);
		} catch (Exception ne) {
			ne.printStackTrace();
			System.out.println(ne.getLocalizedMessage());
		} finally {
			database.recycle();
		}

		return new ResultSetDataHolder2[] {};

	}
}

class Pc {
	Pc parent;
	Map<String, Pc> childMap;
	String universalID;
	String subject;
	String name;
	String ref;

	public Pc getChild(String universalID) {
		return childMap.get(universalID);
	}

	public void addChild(Pc p) {
		if (childMap == null) {
			childMap = new LinkedHashMap<String, Pc>();
		}
		p.parent = this;
		childMap.put(p.universalID, p);
	}

	public boolean hasParent() {
		return parent != null;
	}

	public boolean hasChild() {
		return childMap != null && childMap.size() > 0;
	}

	public boolean hasGrandChild() {
		if (hasChild()) {
			for (Pc p : childMap.values()) {
				if (p.hasChild()) {
					return true;
				}
			}
		}
		return false;
	}

	public void dump(int depth) {
		for (int i = 0; i < depth; i++) {
			System.out.print("  ");
		}
		System.out.println(universalID + " SUBJECT[" + subject + "](" + name
				+ ")");
		if (hasChild()) {
			for (Pc p : childMap.values()) {
				p.dump(depth + 1);
			}
		}
	}

}
