package hiro.yoshioka.sql.notes;

import hiro.yoshioka.classmanager.ClassManager;
import hiro.yoshioka.sdh.DatabaseType;
import hiro.yoshioka.sdh.StringRecordData;
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.notes.reflect.WolfItem;
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 hiro.yoshioka.util.StringUtil;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class NotesRunnerParentAndChildSelection extends AbsNotesRunner
		implements Callable<ResultSetDataHolder2[]> {
	NotesDBTable table;
	ConnectionProperties properties;
	int maxRowNum;
	Set<String> unidSet;
	ResultSetDataHolder2 rdhChild, rdhParent;

	public NotesRunnerParentAndChildSelection(ClassManager manager,
			ConnectionProperties properties, IDBTable table, int maxRowNum) {
		super(manager, properties);
		this.table = (NotesDBTable) table;
		this.properties = properties;
		this.maxRowNum = maxRowNum;
	}

	public NotesRunnerParentAndChildSelection(ClassManager manager,
			ConnectionProperties properties, IDBTable table, Set<String> unidSet) {
		super(manager, properties);
		this.table = (NotesDBTable) table;
		this.properties = properties;
		this.unidSet = unidSet;
		if (unidSet != null) {
			this.maxRowNum = unidSet.size();
		}
	}

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

		// dom
		p.setHost("10.0.0.100");
		p.setAuthenticate(new DBUserPass("user", "password"));

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

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

			NotesRunnerParentAndChildSelection sjd = new NotesRunnerParentAndChildSelection(
					cm, p, tbl, 10);
			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();
		}
	}

	private void doclist2Rdh(WolfDocument doc, boolean isChild)
			throws IllegalArgumentException, MalformedURLException,
			SecurityException, IllegalAccessException,
			InvocationTargetException, ClassNotFoundException,
			NoSuchMethodException {
		if (doc == null) {
			return;
		}
		Set<String> allKeySets = new LinkedHashSet<String>();
		ResultSetDataHolder2 targetRdh = null;
		if (isChild) {
			if (rdhChild == null) {
				for (WolfItem item : doc.getItems()) {
					if (item.isIgnoreItem()) {
						continue;
					}
					allKeySets.add(item.getName());
				}
				allKeySets.add(AbsNotesRunner.UniversalID);
				rdhChild = new ResultSetDataHolder2(
						allKeySets.toArray(new String[allKeySets.size()]),
						null, DatabaseType.DOMINO);
			}
			targetRdh = rdhChild;
		} else {
			if (rdhParent == null) {
				for (WolfItem item : doc.getItems()) {
					if (item.isIgnoreItem()) {
						continue;
					}
					allKeySets.add(item.getName());
				}
				allKeySets.add(AbsNotesRunner.UniversalID);
				rdhParent = new ResultSetDataHolder2(
						allKeySets.toArray(new String[allKeySets.size()]),
						null, DatabaseType.DOMINO);
			}
			targetRdh = rdhParent;
		}
		if (allKeySets.size() == 0) {
			for (String key : targetRdh.getNoRowKeys()) {
				allKeySets.add(key);
			}
		}

		for (WolfItem item : doc.getItems()) {
			if (item.isIgnoreItem()) {
				continue;
			}
			if (!allKeySets.contains(item.getName())) {
				allKeySets.add(item.getName());
				targetRdh.addColumn(item.getName(), null);
			}
		}
		int iCol = 0;

		System.out.println("akkKeys=" + allKeySets);
		StringRecordData[] record = new StringRecordData[allKeySets.size()];
		for (String key : allKeySets) {
			// Object o = obj.getItemValueString(key);
			// if (o != null) {
			// System.out.println(o.getClass());
			// }
			try {
				if (AbsNotesRunner.UniversalID.equals(key)) {
					record[iCol] = new StringRecordData(doc.getUniversalID());
				} else {
					if (doc.hasItem(key)) {
						WolfItem item = doc.getFirstItem(key);
						record[iCol] = getItemValue(doc, key);
						// if (item.isRichText()) {
						// item.saveAttachment(new File("C:/tmp"));
						// }
						item.recycle();
					} else {
						record[iCol] = new StringRecordData(null);
					}
				}
				iCol++;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		targetRdh.addRow(record);
		// System.out.println(obj.generateXML());

	}

	public ResultSetDataHolder2[] callTable() throws Exception {

		WolfDatabase database = getDatabaseByTable(table);

		System.out.println("database =" + database);
		if (!database.isOpen()) {
			database.open();
		}
		try {
			if (unidSet == null) {
				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, 20);
				System.err.println("--------------------");
				System.out.println("result count=" + docs.getCount());
				WolfDocument doc = docs.getFirstDocument();

				doclist2Rdh(doc, true);
				while (doc != null) {
					doc = docs.getNextDocument();
					doclist2Rdh(doc, true);
					System.out
							.println(rdhChild.getRowCount() + "/" + maxRowNum);
					if (rdhChild.getRowCount() >= maxRowNum) {
						System.out.println("break [" + rdhChild.getRowCount()
								+ "]");
						break;
					}
					if (rdhChild.getRowCount() >= 20) {
						System.out.println("break 20[" + rdhChild.getRowCount()
								+ "]");
						break;
					}
				}

			} else {
				for (String unid : unidSet) {
					WolfDocument doc = database.getDocumentByUNID(unid);
					System.out.println("unid=" + unid + "  doc=" + doc);
					doclist2Rdh(doc, true);

					System.out
							.println(rdhChild.getRowCount() + "/" + maxRowNum);
					if (rdhChild.getRowCount() >= maxRowNum) {
						System.out.println("break [" + rdhChild.getRowCount()
								+ "]");
						break;
					}
					if (rdhChild.getRowCount() >= 20) {
						System.out.println("break 20[" + rdhChild.getRowCount()
								+ "]");
						break;
					}

				}
			}
			rdhChild.addColumn("parent", null);
			rdhChild.addColumn("thread_id", null);
			rdhChild.addColumn("type", null);

			Set<String> refSet = new LinkedHashSet<String>();
			for (int i = 0; i < rdhChild.getRowCount(); i++) {
				String ref = rdhChild.getStringData(i, "$REF");
				if (!StringUtil.isEmpty(ref)) {
					refSet.add(ref);
				}
				String uuid = UUID.randomUUID().toString();
				rdhChild.changeString(i, "parent", uuid);
				rdhChild.changeString(i, "thread_id", uuid);
				rdhChild.changeString(i, "type", "6151GP4IDK");
			}
			for (String unid : refSet) {
				WolfDocument doc = database.getDocumentByUNID(unid);
				doclist2Rdh(doc, false);
			}
			rdhParent.addColumn("id", null);
			rdhParent.addColumn("thread_id", null);
			rdhParent.addColumn("type", null);
			String uuid = StringUtil.EMPTY_STRING;
			for (int j = 0; j < rdhChild.getRowCount(); j++) {
				String childuuid = rdhChild.getStringData(j, "$REF");
				String thread_id = rdhChild.getStringData(j, "thread_id");
				rdhParent.changeStringMatchedRow(AbsNotesRunner.UniversalID,
						childuuid, "id", thread_id);
				rdhParent.changeStringMatchedRow(AbsNotesRunner.UniversalID,
						childuuid, "thread_id", thread_id);
			}
			for (int i = 0; i < rdhParent.getRowCount(); i++) {
				rdhParent.changeString(i, "type", "6151GP4IPY");
			}
			String[] keys = rdhChild.getKey();
			for (int i = 0; i < keys.length; i++) {
				if (keys[i].endsWith("Date")) {
					for (int j = 0; j < rdhChild.getRowCount(); j++) {
						String date = rdhChild.getStringData(j, keys[i]);

						if (StringUtil.isEmpty(date)) {
							continue;
						}
						// 2003/04/16 21:24:58 ZE9
						if (date.matches("\\d+/\\d+/\\d+ \\d+:\\d+:\\d+.*")) {
							date = date
									.replaceAll(
											"(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+).*",
											"dt$1-$2-$3 $4:$5:$6");
							rdhChild.changeString(j, i, date);
						}
					}
				}
			}
			keys = rdhParent.getKey();
			for (int i = 0; i < keys.length; i++) {
				if (keys[i].endsWith("Date")) {
					for (int j = 0; j < rdhParent.getRowCount(); j++) {
						String date = rdhParent.getStringData(j, keys[i]);

						if (StringUtil.isEmpty(date)) {
							continue;
						}
						// 2003/04/16 21:24:58 ZE9
						if (date.matches("\\d+/\\d+/\\d+ \\d+:\\d+:\\d+.*")) {
							date = date
									.replaceAll(
											"(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+).*",
											"dt$1-$2-$3 $4:$5:$6");
							rdhParent.changeString(j, i, date);
						}
					}
				}
			}
		} catch (Exception ne) {
			ne.printStackTrace();
			System.out.println(ne.getLocalizedMessage());
		} finally {
		}
		System.out.println("return " + rdhChild);

		return new ResultSetDataHolder2[] { rdhParent, rdhChild };

	}

	private StringRecordData getItemValue(WolfDocument obj, String key)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, SecurityException, NoSuchMethodException {
		Vector v = obj.getItemValue(key);
		if (v == null || v.size() == 0) {
			return new StringRecordData(null);
		}
		StringBuilder buf = new StringBuilder();
		buf.append(v.get(0));
		for (int i = 1; i < v.size(); i++) {
			buf.append(StringUtil.LINE_SEPARATOR).append(v.get(i));
		}
		if ("$FILE".equals(key)) {
			System.out.println("vec=" + obj.getItemValue(key));
			System.out.println("str=" + obj.getItemValueString(key));
		}
		return new StringRecordData(buf.toString());
	}

}
