package cn.net.connor.std.processedit.searchbysql;

import java.io.StringReader;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JTextField;

import com.teamcenter.rac.kernel.TCException;
import com.teamcenter.rac.util.Registry;

import cn.net.connor.std.aifrcp.KDialogController;
import cn.net.connor.std.aifrcp.util.KSqlUtil;
import cn.net.connor.std.aifrcp.util.KUtil;
import cn.net.connor.std.processedit.meopviewfx.bean.KTableRow;
import cn.net.connor.std.processedit.util.KSqlTable;
import cn.net.connor.std.processedit.util.KSqlTable.Config;
import cn.net.connor.std.processedit.util.ProcessUtil;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;

public class SearchBySqlDialogController extends KDialogController {

	
	// private Map<String, JTextComponent> otherComps;
	private SearchBySqlDialog dialog;
	protected List<Config> configs = new ArrayList<Config>();
	protected Map<String, String> searchCols_DB_UI = new LinkedHashMap<>();
	protected Map<String, JTextField> searchComps = new HashMap<String, JTextField>();
	protected KSqlTable tableBean;
	private KTableRow tableRow;
	private static final Registry REG = Registry.getRegistry(SearchBySqlDialogController.class);

	public static void getTableNameBySql(String sql, List<String> headers, List<String> fields) throws JSQLParserException {
		try {
			CCJSqlParserManager pm = new CCJSqlParserManager();
			Statement statement = pm.parse(new StringReader(sql));
			if (statement instanceof Select) {
				Select selectStatement = (Select) statement;
				PlainSelect selectBody = (PlainSelect) selectStatement.getSelectBody();
				List<SelectItem> selectItemlist = selectBody.getSelectItems();
				SelectItem selectItem = null;
				SelectExpressionItem selectExpressionItem = null;
				AllTableColumns allTableColumns = null;
				Alias alias = null;
				if (selectItemlist != null) {
					for (int i = 0; i < selectItemlist.size(); i++) {
						selectItem = selectItemlist.get(i);
						if (selectItem instanceof SelectExpressionItem) {
							selectExpressionItem = (SelectExpressionItem) selectItemlist.get(i);
							alias = selectExpressionItem.getAlias();
							String columnName = "";
							if (alias != null) {
								columnName = alias.getName();
							} else {
								columnName = selectExpressionItem.getExpression().toString();
							}
							headers.add(columnName);
							fields.add(selectExpressionItem.getExpression().toString());
						} else if (selectItem instanceof AllTableColumns) {
							allTableColumns = (AllTableColumns) selectItemlist.get(i);
							headers.add(allTableColumns.toString());
							fields.add(allTableColumns.toString());
						} else {
							headers.add(selectItem.toString());
							fields.add(selectItem.toString());
						}

					}
				}
			}
		} catch (JSQLParserException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean init() throws Exception {
		this.dialog = (SearchBySqlDialog) aifDialog;
		String prefName = dialog.sqlPrefName;
		this.tableRow = dialog.tableRow;
		String[] config = KUtil.getPrefVals(session, prefName);
		int len = KUtil.getLen(config);
		if (len == 0) {
			System.out.println("No Choose Config");
			throw new TCException(REG.getString("novalidchooseconfig.ERROR"));
		}
		String sql = String.join("\n", config);
		System.out.println(">> sql: \n" + sql);
		List<String> headers = new ArrayList<>();
		List<String> fields = new ArrayList<>();
		getTableNameBySql(sql, headers, fields);
		System.out.println(">> headers: " + headers);
		System.out.println(">> fields: " + fields);
		len = headers == null ? 0 : headers.size();
		// Read Config
		for (int i = 0; i < len; i++) {
			String dbColName = headers.get(i);
			String dbFieldName = fields.get(i);
			String[] split = dbColName.replace("\"", "").split("=", -1);
			int splitCnt = KUtil.getLen(split);
			String tableCol = null, propConfig = null;
			int prefW = 100;
			if (splitCnt > 0) {
				tableCol = split[0];
			}
			if (splitCnt > 1) {
				propConfig = split[1];
			}
			if (splitCnt > 2) {
				try {
					prefW = Integer.parseInt(split[2]);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (!KUtil.isEmpty(tableCol)) {
				if (tableCol.startsWith("#")) {
					tableCol = tableCol.substring(1);
					System.out.println(">> Add Search: " + tableCol);
					if (!this.searchCols_DB_UI.containsKey(dbFieldName)) {
						this.searchCols_DB_UI.put(dbFieldName, tableCol);
					}
				}
				this.configs.add(new Config(tableCol, dbFieldName, propConfig, prefW));
			} else {
				System.out.println("ERROR Config: " + dbColName);
			}
			if (dbColName.startsWith("\"")) {
				sql = sql.replace(dbColName, "");
			}
		}
		System.out.println("Formated Sql: \n" + sql);
		this.tableBean = new KSqlTable(configs, sql);
		return true;
	}

	public void doSearch() throws Exception {
		Map<String, String> searchInfo = new HashMap<String, String>();
		System.out.println("Perform Search..");
		for (String colName : this.searchComps.keySet()) {
			String value = this.searchComps.get(colName).getText();
			if (!KUtil.isEmpty(value)) {
				System.out.println(">> " + colName + " = " + value);
				searchInfo.put(colName, value);
			}
		}
		Connection conn = KSqlUtil.getOracleConnection(session, ProcessUtil.PREF_DB_CONN);
		try {
			this.tableBean.performSearch(searchInfo, conn);
		} finally {
			KSqlUtil.free(conn);
		}
	}

	public void doSelect() throws Exception {
		LinkedHashMap<Config, String> data = this.tableBean.getSelectedData();
		if (data == null || data.size() <= 0) {
			System.out.println("No Select Info");
			dialog.disposeDialog();
			return;
		}
		System.out.println("Selected Row: " + Arrays.toString(data.values().toArray()));
		for (Config colConfig : data.keySet()) {
			String val = data.get(colConfig);
			String addition = colConfig.getAdditionalInfo();
			if (KUtil.isEmpty(addition)) {
				continue;
			}
			this.tableRow.setValueByPropName(addition, val);
		}
		dialog.disposeDialog();
	}

}
