package hiro.yoshioka.sql.util;

import hiro.yoshioka.classmanager.ClassManager;
import hiro.yoshioka.extract.ArchiveManager;
import hiro.yoshioka.sdh.DatabaseType;
import hiro.yoshioka.sql.DataBaseFactory;
import hiro.yoshioka.sql.ITransactionSQL;
import hiro.yoshioka.sql.MySQL;
import hiro.yoshioka.sql.SQLServerSQL;
import hiro.yoshioka.sql.engine.SQLServerThread;
import hiro.yoshioka.sql.evernote.EverNoteSQL;
import hiro.yoshioka.sql.params.ConnectionProperties;
import hiro.yoshioka.sql.params.DBResourceCapturingFilter;
import hiro.yoshioka.sql.params.DBUserPass;
import hiro.yoshioka.sql.twitter.TwitterUtil;
import hiro.yoshioka.sql.twitter.WolfAccessToken;
import hiro.yoshioka.util.ColorNameEnum;
import hiro.yoshioka.util.ColorUtil;
import hiro.yoshioka.util.StringUtil;

import java.io.File;
import java.sql.Driver;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;

import twitter4j.TwitterException;

public class DBConfigDialog extends TitleAreaDialog implements KeyListener,
		SelectionListener {
	static enum MODE {
		ADD, EDIT, CLONE;
	}

	MODE mode;
	private DatabaseType databaseType;
	private DatabaseType beforeDatabaseType;
	static String[] SYSOP = { StringUtil.EMPTY_STRING, "sysdba", "sysoper" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	Combo fCombo;
	Combo fSysCombo;
	Label fComboDriverNameLbl;

	Set<File> jarFileSet = new LinkedHashSet<File>();
	Label fUrlOrHostLabel;
	// Filters
	Label fCategoriesPatternLabel;
	Label fFilePathPatternLabel;
	Label fDBObjectPattern1Label;
	Label fDBObjectPattern2Label;
	Label fDatabaseLabel;
	Label fRecursiveSearchDepthLabel;
	Label fKeepAliveIntervalLabel;

	Text fCategoriesRegexText;
	Text fFilePathText;
	Text fDBObjectRegex1Text;
	Text fDBObjectRegex2Text;

	Text fUrlOrHostText;
	Text fDatabaseText;
	Text fUserText;
	Text fPasswordText;
	Text fDisplayNameText;
	Spinner fRecursiveSearchSpin;
	Spinner fKeepAliveIntervalSpin;

	Button fCheckDBMSButton;
	Button fCheckAutoCommitButton;
	Button fCheckSerializeButton;
	Button fCaptureResourceAfterTheConnectProcessButton;
	Button fCaptureWithColumnInfoButton;
	Button fCaptureWithDDLButton;
	Button fCaptureWithTableButton;
	Button fCaptureWithViewButton;
	Button fCaptureWithProcedureButton;
	Button fCaptureWithSequenceButton;
	Button fCaptureWithTriggerButton;
	boolean createdEditors;
	boolean wasChangedUrl = false;
	ConnectionProperties fConnectionProperties;
	CTabFolder tabFolder;
	Group baseGroup;
	// --------------------------
	Button nothingBtn, ignoreBtn, matchBtn;
	// --------------------------
	WolfAccessToken accessToken;

	boolean initializing, checked;
	int max = Display.getCurrent().getBounds().width - 100;

	@Override
	protected boolean isResizable() {
		return true;
	}

	public DBConfigDialog(Shell shell, String[] jarfiles,
			ConnectionProperties selectedItem, MODE mode) {
		super(shell);
		for (String jarFile : jarfiles) {
			File f = new File(jarFile);
			if (f.exists() && f.isFile()) {
				jarFileSet.add(f);
			}
		}
		fConnectionProperties = selectedItem;
		this.mode = mode;
	}

	Text createText(Composite parent) {
		Text ret = new Text(parent, SWT.BORDER);
		// ret.setEditable(false);
		ret.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		return ret;
	}

	private Label createLabel(Composite parent, String text) {
		Label lb = new Label(parent, SWT.NONE);
		lb.setText(text);
		return lb;
	}

	private void resetResourceFilterSetting() {
		String regrexLabel1Name = Messages
				.getString("DBConfigDialog.dbobjectPattern1"); //$NON-NLS-1$
		switch (this.databaseType) {
		case DOMINO:
			fDBObjectRegex1Text.setMessage("^(Lotus Notes|Domino).*"); //$NON-NLS-1$
			break;
		case POSTGRES:
			regrexLabel1Name = Messages.getString("DBConfigDialog.NameSpace"); //$NON-NLS-1$
			fDBObjectRegex1Text.setMessage("pg_catalog"); //$NON-NLS-1$
			// if (!this.databaseType.equals(beforeDatabaseType)) {
			// ignoreBtn.setSelection(true);
			// matchBtn.setSelection(false);
			// nothingBtn.setSelection(false);
			// }
			break;
		default:
			break;
		}
		fDBObjectPattern1Label.setText(regrexLabel1Name);
		fDBObjectRegex1Text.setEnabled(!nothingBtn.getSelection());
		fDBObjectRegex2Text.setEnabled(!nothingBtn.getSelection());
		Color color = nothingBtn.getSelection() ? ColorUtil
				.getColor(ColorNameEnum.GRAY) : ColorUtil
				.getColor(ColorNameEnum.BLACK);
		fDBObjectPattern1Label.setForeground(color);
		fDBObjectPattern2Label.setForeground(color);

		if (databaseType.enableNsaFilePathFilter()) {
			fFilePathText.setVisible(true);
			fFilePathPatternLabel.setVisible(true);
			fFilePathText.setEnabled(!nothingBtn.getSelection());
			fFilePathPatternLabel.setForeground(color);
		} else {
			fFilePathText.setVisible(false);
			fFilePathPatternLabel.setVisible(false);
		}
		if (databaseType.enableCategoryFilter()) {
			fCategoriesPatternLabel.setForeground(color);
			if (databaseType.isOracle()) {
				fCategoriesPatternLabel.setText(Messages
						.getString("DBConfigDialog.SCHEMA")); //$NON-NLS-1$
				fCategoriesRegexText.setMessage(fConnectionProperties
						.getAuthenticate().user.toUpperCase());
			} else if (databaseType.isDomino()) {
				fCategoriesPatternLabel.setText(Messages
						.getString("DBConfigDialog.Category")); //$NON-NLS-1$
				fCategoriesRegexText.setMessage(Messages
						.getString("DBConfigDialog.NotesHelp")); //$NON-NLS-1$
			}
			fCategoriesRegexText.setVisible(true);
			fCategoriesPatternLabel.setVisible(true);
		} else {
			fCategoriesRegexText.setVisible(false);
			fCategoriesPatternLabel.setVisible(false);
		}
	}

	private void resetTab() {
		try {
			// -------------------------------------------------------------------
			// URL or Host
			// -------------------------------------------------------------------
			String suggestUrl = DataBaseFactory
					.getSuggestURL(this.databaseType);
			fUrlOrHostText.setMessage(suggestUrl);
			if (wasChangedUrl) {
				if (MessageDialog.openConfirm(this.getShell(), "Confirm", //$NON-NLS-1$
						Messages.getString("DBConfigDialog.ChangeURL"))) { //$NON-NLS-1$
					fUrlOrHostText.setText(suggestUrl);
					wasChangedUrl = false;
				}
			} else {
				fUrlOrHostText.setText(suggestUrl);
			}

			fUrlOrHostText.setVisible(true);
			fUserText.setEditable(true);
			fPasswordText.setEditable(true);
			fUrlOrHostLabel.setText("URL: "); //$NON-NLS-1$ 
			switch (this.databaseType) {
			case MONGO:
				fUrlOrHostLabel.setText(Messages
						.getString("DBConfigDialog.Host")); //$NON-NLS-1$
				break;
			case DOMINO:
				fUrlOrHostLabel.setText(Messages
						.getString("DBConfigDialog.Host")); //$NON-NLS-1$
				break;
			case POSTGRES:
				break;
			case EVERNOTE:
				fUrlOrHostText.setMessage(EverNoteSQL.getHostString());
				fUrlOrHostLabel.setText(Messages
						.getString("DBConfigDialog.Host")); //$NON-NLS-1$
				break;
			case SQLITE:
				fUserText.setEditable(false);
				fPasswordText.setEditable(false);
				break;
			case TWITTER:
				fUrlOrHostText.setVisible(false);
				fUserText.setEditable(false);
				fPasswordText.setEditable(false);
				if (mode == MODE.ADD) {
					try {
						accessToken = TwitterUtil
								.getAccessTokenAtAuthorizationSite(getShell());
						if (accessToken != null) {
							fUserText.setText("" + accessToken.getUserId()); //$NON-NLS-1$
						}
						fPasswordText.setText(accessToken.getToken());
					} catch (TwitterException e) {
						e.printStackTrace();
					}
				}
				break;
			default:
				break;
			}
			resetResourceFilterSetting();

			fCategoriesRegexText.setEnabled(!nothingBtn.getSelection());
			fCaptureWithTableButton
					.setText(databaseType.isDomino() ? "Form" : "Table"); //$NON-NLS-1$ //$NON-NLS-2$
			if (mode == MODE.ADD) {
				fCaptureWithTableButton
						.setSelection(databaseType.isDomino() ? false : true);
			}
			if (databaseType.needsDatabaseNameDefine()) {
				fDatabaseLabel.setForeground(ColorUtil
						.getColor(ColorNameEnum.BLACK));
				fDatabaseText.setEnabled(true);
			} else {
				fDatabaseLabel.setForeground(ColorUtil
						.getColor(ColorNameEnum.GRAY));
				fDatabaseText.setEnabled(false);
			}
			if (databaseType.enableRecursiveSearch()) {
				fRecursiveSearchSpin.setEnabled(true);
				fRecursiveSearchDepthLabel.setForeground(ColorUtil
						.getColor(ColorNameEnum.BLACK));
			} else {
				fRecursiveSearchSpin.setEnabled(false);
				fRecursiveSearchDepthLabel.setForeground(ColorUtil
						.getColor(ColorNameEnum.GRAY));
			}

			if (databaseType.isAutoCommitRecommended()
					&& fUserText.getText().length() == 0) {
				fCheckAutoCommitButton.setSelection(true);
			}
			if (databaseType.forceAutoCommitTrue()) {
				fCheckAutoCommitButton.setSelection(true);
				fCheckAutoCommitButton.setEnabled(false);
			} else {
				fCheckAutoCommitButton.setEnabled(true);
			}
			validate();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void validate() {
		if (this.testConnectButton != null) {
			testConnectButton.setEnabled(false);
		}
		Button bt = getButton(IDialogConstants.OK_ID);
		if (bt == null) {
			return;
		}
		bt.setEnabled(false);
		String displayName = fDisplayNameText.getText().trim();
		if (StringUtil.isEmpty(displayName)) {
			bt.setEnabled(false);
			setErrorMessage(Messages
					.getString("DBConfigDialog.Input_DISPLAY_NAME")); //$NON-NLS-1$
			return;
		}
		if (SQLServerThread.getSQLServer().getConnectionSettingBean()
				.isDefinedDisplayOf(displayName, fConnectionProperties)) {
			bt.setEnabled(false);
			setErrorMessage(String.format(
					"Display String[%s] is already defined ", displayName)); //$NON-NLS-1$
			return;
		}
		if (fCombo.getSelectionIndex() < 0) {
			setErrorMessage(Messages
					.getString("DBConfigDialog.Choose_Driver_Class")); //$NON-NLS-1$
			return;
		}
		switch (databaseType) {
		case EVERNOTE:
			String mes = EverNoteSQL.validateHost(fUrlOrHostText.getText());
			if (mes != null) {
				setErrorMessage(mes);
				return;
			}
			break;
		case TWITTER:
			if (accessToken == null) {
				bt.setEnabled(false);
				setErrorMessage("please authorize me!"); //$NON-NLS-1$
				return;
			}
			break;
		case MONGO:
		case DOMINO:
			if (StringUtil.isEmpty(fUrlOrHostText.getText().trim())) {
				setErrorMessage(Messages.getString("DBConfigDialog.Input_Host")); //$NON-NLS-1$
				return;
			}
			break;
		default:
			if (StringUtil.isEmpty(fUrlOrHostText.getText().trim())) {
				setErrorMessage(Messages.getString("DBConfigDialog.Input_URL")); //$NON-NLS-1$
				return;
			}
		}
		if (!databaseType.isSQLite()) {
			if (StringUtil.isEmpty(fUserText.getText().trim())) {
				setErrorMessage(Messages
						.getString("DBConfigDialog.messageInputUser")); //$NON-NLS-1$
				return;
			}
		}
		setErrorMessage(null);
		bt.setEnabled(true);

		if (this.testConnectButton != null && databaseType.enableKeepAlive()) {
			testConnectButton.setEnabled(true);
		}
	}

	private GridData createTextGridData() {
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		data.widthHint = 210;
		return data;
	}

	protected Control createDialogArea(Composite parent) {

		getShell().setText(
				Messages.getString("DBConfigDialog.Set_ConnectionProperties")); //$NON-NLS-1$
		Composite inner = new Composite(parent, SWT.NONE);
		inner.setLayoutData(new GridData(GridData.FILL_BOTH));
		GridLayout layout = new GridLayout(1, false);
		inner.setLayout(layout);
		Group driverGroup = createGroup(inner,
				Messages.getString("DBConfigDialog.JDBC_Driver_Class_1"), 2); //$NON-NLS-1$
		fCombo = new Combo(driverGroup, SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.BORDER);
		fCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		GridData gd200 = new GridData();
		gd200.widthHint = 200;
		gd200.minimumWidth = 200;
		fComboDriverNameLbl = new Label(driverGroup, SWT.BORDER);
		fComboDriverNameLbl.setLayoutData(gd200);
		// tabFolder = new CTabFolder(inner, SWT.NONE);
		GridData gd = new GridData(GridData.FILL_BOTH);
		gd.horizontalSpan = 2;
		// tabFolder.setLayoutData(gd);

		baseGroup = createGroup(inner,
				Messages.getString("DBConfigDialog.Basic_Properties_2"), 4); //$NON-NLS-1$
		baseGroup.setLayoutData(gd);

		createLabel(baseGroup,
				Messages.getString("DBConfigDialog.DISPLAY_NAME")); //$NON-NLS-1$
		fDisplayNameText = new Text(baseGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fDisplayNameText.setLayoutData(createTextGridData());

		fDatabaseLabel = createLabel(baseGroup,
				Messages.getString("DBConfigDialog.DATABASE")); //$NON-NLS-1$
		fDatabaseText = new Text(baseGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fDatabaseText.setLayoutData(createTextGridData());

		fUrlOrHostLabel = createLabel(baseGroup, "Host: "); //$NON-NLS-1$ 
		fUrlOrHostText = new Text(baseGroup, SWT.SINGLE | SWT.BORDER);
		fUrlOrHostText.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (!initializing) {
					wasChangedUrl = true;
				}
			}
		});
		GridData gd_url = createTextGridData();
		gd_url.horizontalSpan = 3;
		fUrlOrHostText.setLayoutData(gd_url);

		createLabel(baseGroup, Messages.getString("DBConfigDialog.USER")); //$NON-NLS-1$
		fUserText = new Text(baseGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fUserText.setLayoutData(createTextGridData());
		fUserText.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				checkAndSetOracleFilter();
			}
		});
		fUserText.addKeyListener(this);

		createLabel(baseGroup, Messages.getString("DBConfigDialog.PASSWORD")); //$NON-NLS-1$
		fPasswordText = new Text(baseGroup, SWT.SINGLE | SWT.BORDER
				| SWT.PASSWORD); //$NON-NLS-1$
		fPasswordText.setLayoutData(createTextGridData());

		fRecursiveSearchDepthLabel = createLabel(baseGroup,
				Messages.getString("DBConfigDialog.RecursiveSerch")); //$NON-NLS-1$
		fRecursiveSearchSpin = new Spinner(baseGroup, SWT.BORDER);
		fRecursiveSearchSpin.setValues(1, 0, 5, 0, 1, 1);
		fRecursiveSearchSpin.setLayoutData(new GridData(
				GridData.FILL_HORIZONTAL));
		createLabel(baseGroup, Messages.getString("DBConfigDialog.AuthDBA")); //$NON-NLS-1$

		fSysCombo = new Combo(baseGroup, SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.BORDER);
		fSysCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fSysCombo.setItems(SYSOP);
		fSysCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		createLabel(baseGroup, Messages.getString("DBConfigDialog.DBMS_OUTPUT")); //$NON-NLS-1$
		fCheckDBMSButton = new Button(baseGroup, SWT.CHECK);
		fCheckDBMSButton.setText(Messages
				.getString("DBConfigDialog.display_in_ErrorView")); //$NON-NLS-1$
		fCheckDBMSButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		fCombo.addSelectionListener(this);

		createLabel(baseGroup, Messages.getString("DBConfigDialog.AutoCommit")); //$NON-NLS-1$
		fCheckAutoCommitButton = new Button(baseGroup, SWT.CHECK);
		fCheckAutoCommitButton
				.setText(Messages.getString("DBConfigDialog.Yes")); //$NON-NLS-1$
		fCheckAutoCommitButton.setLayoutData(new GridData(
				GridData.FILL_HORIZONTAL));

		fKeepAliveIntervalLabel = createLabel(baseGroup,
				Messages.getString("DBConfigDialog.KeepAliveInterval")); //$NON-NLS-1$
		fKeepAliveIntervalSpin = new Spinner(baseGroup, SWT.BORDER);
		fKeepAliveIntervalSpin.setValues(280, 0, 1800, 0, 1, 1);
		fKeepAliveIntervalSpin.setLayoutData(new GridData(
				GridData.FILL_HORIZONTAL));

		createdEditors = true;

		// [3] capture
		// ----------------------------------------------------------------------
		Group optionalGroup = createGroup(
				inner,
				Messages.getString("DBConfigDialog.DBResource_Capturing_Options_3"), 2); //$NON-NLS-1$
		gd = new GridData(GridData.FILL_BOTH);
		gd.horizontalSpan = 2;
		optionalGroup.setLayoutData(gd);

		createLabel(optionalGroup,
				Messages.getString("DBConfigDialog.Capture_With")); //$NON-NLS-1$
		Composite captureComposite = new Composite(optionalGroup, SWT.NONE);
		captureComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		captureComposite.setLayout(new FillLayout());
		fCaptureWithTableButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithTableButton.setText("Table"); //$NON-NLS-1$
		fCaptureWithViewButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithViewButton.setText(Messages
				.getString("DBConfigDialog.View")); //$NON-NLS-1$
		fCaptureWithProcedureButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithProcedureButton.setText("Procedure"); //$NON-NLS-1$
		fCaptureWithColumnInfoButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithColumnInfoButton.setText(Messages
				.getString("DBConfigDialog.Column_Field")); //$NON-NLS-1$
		// line2
		createLabel(optionalGroup, StringUtil.EMPTY_STRING);
		captureComposite = new Composite(optionalGroup, SWT.NONE);
		captureComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		captureComposite.setLayout(new FillLayout());
		fCaptureWithDDLButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithDDLButton.setText(Messages.getString("DBConfigDialog.DDL")); //$NON-NLS-1$
		fCaptureWithTriggerButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithTriggerButton.setText("Trigger"); //$NON-NLS-1$
		fCaptureWithSequenceButton = new Button(captureComposite, SWT.CHECK);
		fCaptureWithSequenceButton.setText("Sequence"); //$NON-NLS-1$
		createLabel(captureComposite, StringUtil.HALF_SPACE__STRING);

		createLabel(optionalGroup, StringUtil.HALF_SPACE__STRING);
		Composite filterComposite = new Composite(optionalGroup, SWT.NONE);
		filterComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		filterComposite.setLayout(new GridLayout());
		// [4] capture
		optionalGroup = createGroup(filterComposite, "Filter", 2); //$NON-NLS-1$
		gd = new GridData(GridData.FILL_BOTH);
		gd.horizontalSpan = 2;
		optionalGroup.setLayoutData(gd);
		createLabel(optionalGroup,
				Messages.getString("DBConfigDialog.ResourceFilter")); //$NON-NLS-1$
		Composite radioComposite = new Composite(optionalGroup, SWT.NONE);
		radioComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		nothingBtn = new Button(radioComposite, SWT.RADIO);
		nothingBtn.setText(DBResourceCapturingFilter.NOTHING.name());
		nothingBtn.addSelectionListener(this);
		ignoreBtn = new Button(radioComposite, SWT.RADIO);
		ignoreBtn.setText(DBResourceCapturingFilter.IGNORE.name());
		ignoreBtn.addSelectionListener(this);
		matchBtn = new Button(radioComposite, SWT.RADIO);
		matchBtn.setText(DBResourceCapturingFilter.MATCHES.name());
		matchBtn.addSelectionListener(this);
		radioComposite.setLayout(new FillLayout());

		fCategoriesPatternLabel = createLabel(optionalGroup,
				"Catalog Pattern: "); //$NON-NLS-1$ 
		fCategoriesRegexText = new Text(optionalGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fCategoriesRegexText.setLayoutData(createTextGridData());

		fFilePathPatternLabel = createLabel(optionalGroup,
				Messages.getString("DBConfigDialog.filePathPattern")); //$NON-NLS-1$
		fFilePathText = new Text(optionalGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fFilePathText.setLayoutData(createTextGridData());

		fDBObjectPattern1Label = createLabel(optionalGroup,
				Messages.getString("DBConfigDialog.dbobjectPattern1")); //$NON-NLS-1$
		fDBObjectRegex1Text = new Text(optionalGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fDBObjectRegex1Text.setLayoutData(createTextGridData());
		fDBObjectPattern2Label = createLabel(optionalGroup,
				Messages.getString("DBConfigDialog.dbobjectPattern2")); //$NON-NLS-1$
		fDBObjectRegex2Text = new Text(optionalGroup, SWT.SINGLE | SWT.BORDER); //$NON-NLS-1$
		fDBObjectRegex2Text.setLayoutData(createTextGridData());

		Group theOtherOptionalGroup = createGroup(inner,
				Messages.getString("DBConfigDialog.TheOtherOptions_4"), 2); //$NON-NLS-1$
		createLabel(theOtherOptionalGroup,
				Messages.getString("DBConfigDialog.AftertheConnecteProcess")); //$NON-NLS-1$
		fCaptureResourceAfterTheConnectProcessButton = new Button(
				theOtherOptionalGroup, SWT.CHECK | SWT.BORDER);
		fCaptureResourceAfterTheConnectProcessButton.setText(Messages
				.getString("DBConfigDialog.autoRecapture")); //$NON-NLS-1$
		fCaptureResourceAfterTheConnectProcessButton
				.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fCaptureResourceAfterTheConnectProcessButton.setSelection(true);

		createLabel(theOtherOptionalGroup,
				Messages.getString("DBConfigDialog.Serialize")); //$NON-NLS-1$
		fCheckSerializeButton = new Button(theOtherOptionalGroup, SWT.CHECK
				| SWT.BORDER);
		fCheckSerializeButton.setSelection(true);
		fCheckSerializeButton.setText(Messages
				.getString("DBConfigDialog.SaveResource")); //$NON-NLS-1$
		fCheckSerializeButton.setLayoutData(new GridData(
				GridData.FILL_HORIZONTAL));
		fUrlOrHostText.addKeyListener(this);
		fDisplayNameText.addKeyListener(this);

		resetCombo();
		init();

		return parent;
	}

	private Group createGroup(Composite parent, String title, int columns) {
		Group group = new Group(parent, SWT.NONE);
		group.setText(title);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		gd.grabExcessVerticalSpace = true;
		group.setLayoutData(gd);
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = columns;
		group.setLayout(gridLayout);
		return group;
	}

	@Override
	protected Control createButtonBar(Composite parent) {
		Control ret = super.createButtonBar(parent);
		validate();
		return ret;
	}

	private final int TEST_CONNECT_BUTTON_ID = 10560824;
	private Button testConnectButton;

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		testConnectButton = createButton(parent, TEST_CONNECT_BUTTON_ID,
				Messages.getString("DBConfigDialog.CheckConnection"), false); //$NON-NLS-1$
		// testConnectButton.setEnabled(false);
		super.createButtonsForButtonBar(parent);
	}

	@Override
	protected void buttonPressed(int buttonId) {
		super.buttonPressed(buttonId);
		if (TEST_CONNECT_BUTTON_ID == buttonId) {
			ConnectionProperties p = (ConnectionProperties) fConnectionProperties
					.cloneWithoutDBRoot();
			setConnectionProperties(p);
			ITransactionSQL sql = DataBaseFactory.createSQL(p);
			try {
				Boolean b = sql.isAlive(p);
				if (b == null) {
					MessageDialog.openInformation(getShell(), "Result", //$NON-NLS-1$
							"Sorry. couldn't check. not support yet."); //$NON-NLS-1$
				} else {
					if (b) {
						MessageDialog
								.openInformation(getShell(),
										"Result", //$NON-NLS-1$
										Messages.getString("DBConfigDialog.ConnectSuccessful")); //$NON-NLS-1$
					}
				}
			} catch (Exception e) {
				MessageDialog
						.openError(getShell(),
								"Result", //$NON-NLS-1$
								String.format(
										Messages.getString("DBConfigDialog.ConnectFailure"), e.getMessage())); //$NON-NLS-1$
			}
		}
	}

	@Override
	protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) {
		Rectangle rect = super.getConstrainedShellBounds(preferredSize);
		if (rect.width > max) {
			rect.width = max;
		}
		return rect;
	}

	private void setConnectionProperties(ConnectionProperties p) {
		try {
			if (fCombo.getSelectionIndex() == -1) {
				super.okPressed();
				return;
			}
			String dbName = StringUtil.EMPTY_STRING;
			String user = fUserText.getText();
			String pass = fPasswordText.getText();

			Pattern P = null;
			Matcher m = null;
			DatabaseType databaseType = DatabaseType.parse(fCombo.getText());
			switch (databaseType) {
			case ORACLE:
				P = Pattern.compile("jdbc:oracle:thin:@([^:]+):"); //$NON-NLS-1$
				m = P.matcher(fUrlOrHostText.getText());
				if (m.find()) {
					p.setHost(m.group(1));
				}
				p.setInternaelLogin(fSysCombo.getText());
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				p.setWritableDBMS_PutLine(fCheckDBMSButton.getSelection());
				break;
			case MONGO:
				dbName = fDatabaseText.getText();
				p.setHost(fUrlOrHostText.getText());
				p.setRecursiveSearchDepth(fRecursiveSearchSpin.getSelection());
				break;
			case DOMINO:
				p.setHost(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				break;
			case HSQL:
				P = Pattern.compile("jdbc:hsqldb:hsql://([^/]+)/"); //$NON-NLS-1$
				m = P.matcher(fUrlOrHostText.getText());
				if (m.find()) {
					p.setHost(m.group(1));
				}
				p.setURLString(fUrlOrHostText.getText());
				break;
			case SQLITE:
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				break;
			case TWITTER:
				p.setAccessToken(accessToken);
				break;
			case POSTGRES:
				P = Pattern.compile("jdbc:postgresql://([^/]+)/.+"); //$NON-NLS-1$
				m = P.matcher(fUrlOrHostText.getText());
				if (m.find()) {
					p.setHost(m.group(1));
				}
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				break;
			case MYSQL:
				p.setHost(MySQL.getHostString(fUrlOrHostText.getText()));
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				break;
			case MS_SQLSERVER:
				p.setHost(SQLServerSQL.getHostString(fUrlOrHostText.getText()));
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
				break;
			case EVERNOTE:
				p.setHost(fUrlOrHostText.getText());
				break;
			default:
				p.setURLString(fUrlOrHostText.getText());
				p.setDriverFilePath(getComboSelectionFile().getAbsolutePath());
			}

			p.setCapturingFilter(DBResourceCapturingFilter.NOTHING);
			if (!nothingBtn.getSelection()) {
				if (ignoreBtn.getSelection()) {
					p.setCapturingFilter(DBResourceCapturingFilter.IGNORE);
				} else {
					p.setCapturingFilter(DBResourceCapturingFilter.MATCHES);
				}
				p.addCalalogRegrex(fCategoriesRegexText.getText());
				p.addFilePathRegrex(fFilePathText.getText());
				p.addTitleRegrex(fDBObjectRegex1Text.getText());
				p.addTitleRegrex(fDBObjectRegex2Text.getText());
			}
			p.setCaptureWithTableInfo(fCaptureWithTableButton.getSelection());
			p.setCaptureWithViewInfo(fCaptureWithViewButton.getSelection());
			p.setCaptureWithProcedureInfo(fCaptureWithProcedureButton
					.getSelection());
			p.setCaptureWithSequenceInfo(fCaptureWithSequenceButton
					.getSelection());
			p.setCaptureWithTriggerInfo(fCaptureWithTriggerButton
					.getSelection());
			p.setDriverName(fCombo.getText());
			p.setDisplayString(fDisplayNameText.getText());
			p.setAuthenticate(dbName, user, pass);
			p.setSerializableDBRoot(fCheckSerializeButton.getSelection());
			p.setCaptureResourceAfterTheConnectProcess(fCaptureResourceAfterTheConnectProcessButton
					.getSelection());
			p.setCaptureWithColumnInfo(fCaptureWithColumnInfoButton
					.getSelection());
			p.setCaptureWithDDL(fCaptureWithDDLButton.getSelection());
			if (databaseType.forceAutoCommitTrue()) {
				fCheckAutoCommitButton.setSelection(true);
			}
			p.setAutoCommit(fCheckAutoCommitButton.getSelection());
			p.setKeepAliveInterval(fKeepAliveIntervalSpin.getSelection());
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	protected void okPressed() {
		setConnectionProperties(fConnectionProperties);
		close();
	}

	public ConnectionProperties getConnectionProperties() {
		return fConnectionProperties;
	}

	private File getComboSelectionFile() {
		Object o = fCombo.getData(fCombo.getText());
		if (o == null) {
			return null;
		}
		return (File) o;
	}

	void init() {
		initializing = true;
		for (int j = 0; j < fCombo.getItemCount(); j++) {
			if (fCombo.getItem(j).equals(fConnectionProperties.getDriverName())) {
				fCombo.select(j);
				break;
			}
		}

		this.databaseType = DatabaseType.parse(fCombo.getText());
		this.beforeDatabaseType = databaseType;
		DBUserPass dup = fConnectionProperties.getAuthenticate();
		if (dup == null) {
			dup = new DBUserPass();
			fConnectionProperties.setAuthenticate(dup);
		}
		switch (fConnectionProperties.getCapturingFilter()) {
		case NOTHING:
			nothingBtn.setSelection(true);
			break;
		case IGNORE:
			ignoreBtn.setSelection(true);
			break;
		case MATCHES:
			matchBtn.setSelection(true);
			break;
		}
		if (!nothingBtn.getSelection() && !ignoreBtn.getSelection()
				&& !matchBtn.getSelection()) {
			nothingBtn.setSelection(true);
		}
		comboChange();
		if (mode == MODE.ADD) {
		} else {
			fKeepAliveIntervalSpin.setSelection(fConnectionProperties
					.getKeepAliveInterval());
			wasChangedUrl = true;
			boolean foundFile = false;
			for (File f : jarFileSet) {
				File f2 = new File(fConnectionProperties.getDriverFilePath());
				if (f.equals(f2)) {
					if (f.exists()) {
						foundFile = true;
					}
					break;
				}
			}
			if (foundFile) {
				fCombo.setEnabled(false);
			} else {
				setErrorMessage("File not found. [" //$NON-NLS-1$
						+ fConnectionProperties.getDriverFilePath() + "]"); //$NON-NLS-1$
			}
			// fDatabaseText.setVisible(false);
		}
		fDatabaseText.setText(dup.db);
		fUserText.setText(dup.user);
		fPasswordText.setText(dup.pass);
		fDisplayNameText.setText(fConnectionProperties.getDisplayString());
		switch (this.databaseType) {
		case MONGO:
			fRecursiveSearchSpin.setSelection(fConnectionProperties
					.getRecursiveSearchDepth());
			break;
		case DOMINO:
			fRecursiveSearchSpin.setSelection(fConnectionProperties
					.getRecursiveSearchDepth());
			fUrlOrHostText.setText(fConnectionProperties.getHost());
			break;
		case TWITTER:
			if (mode != MODE.ADD) {
				fUserText.setEditable(false);
				fPasswordText.setEditable(false);
				accessToken = fConnectionProperties.getAccessToken();
				if (accessToken == null) {
					fUserText.setText(StringUtil.EMPTY_STRING);
					fPasswordText.setText(StringUtil.EMPTY_STRING);
					try {
						accessToken = TwitterUtil
								.getAccessTokenAtAuthorizationSite(getShell());
						if (accessToken != null) {
							fUserText.setText("" + accessToken.getUserId()); //$NON-NLS-1$
						}
						fPasswordText.setText(accessToken.getToken());
					} catch (TwitterException e) {
						e.printStackTrace();
					}
				}
			}
			break;
		default:
			fUrlOrHostText.setText(fConnectionProperties.getURLString());
		}
		fCaptureWithColumnInfoButton.setSelection(fConnectionProperties
				.isCaptureWithColumnInfo());
		fCaptureResourceAfterTheConnectProcessButton
				.setSelection(fConnectionProperties
						.isCaptureResourceAfterTheConnectProcess());
		fCaptureWithDDLButton.setSelection(fConnectionProperties
				.isCaptureWithDDL());
		fCaptureWithTableButton.setSelection(fConnectionProperties
				.isCaptureWithTableInfo());
		fCaptureWithViewButton.setSelection(fConnectionProperties
				.isCaptureWithViewInfo());
		fCaptureWithProcedureButton.setSelection(fConnectionProperties
				.isCaptureWithProcedureInfo());
		fCaptureWithSequenceButton.setSelection(fConnectionProperties
				.isCaptureWithSequenceInfo());
		fCaptureWithTriggerButton.setSelection(fConnectionProperties
				.isCaptureWithTriggerInfo());
		fCheckSerializeButton.setSelection(fConnectionProperties
				.isSerializableDBRoot());
		if (fConnectionProperties.getCalalogRegrex().size() > 0) {
			fCategoriesRegexText.setText((String) fConnectionProperties
					.getCalalogRegrex().toArray()[0]);
		}
		if (fConnectionProperties.getFilePathRegrex().size() > 0) {
			fFilePathText.setText((String) fConnectionProperties
					.getFilePathRegrex().toArray()[0]);
		}
		String[] titleRegex = fConnectionProperties.getTitleRegres().toArray(
				new String[0]);
		if (titleRegex.length > 0) {
			fDBObjectRegex1Text.setText(titleRegex[0]);
			if (titleRegex.length > 1) {
				fDBObjectRegex2Text.setText(titleRegex[1]);
			}
		}
		fSysCombo.setText(fConnectionProperties.getInternaelLogin());
		fCheckDBMSButton.setSelection(fConnectionProperties
				.isWritableDBMS_PutLine());
		fCheckAutoCommitButton.setSelection(fConnectionProperties
				.isAutoCommit());
		initializing = false;
	}

	private void resetCombo() {
		ClassManager clazz = new ClassManager();
		try {
			fCombo.removeAll();
			for (File f : jarFileSet) {
				ArchiveManager arc = new ArchiveManager();
				String[] targets = arc.lookup2Strings(f, ".*[.]class"); //$NON-NLS-1$
				String[] targets2 = new String[targets.length];
				for (int j = 0; j < targets.length; j++) {
					targets2[j] = targets[j].replaceAll("[/\\\\]", ".") //$NON-NLS-1$ //$NON-NLS-2$
							.replaceFirst("[.]class", //$NON-NLS-1$
									StringUtil.EMPTY_STRING);
				}
				clazz.add_lib(f);
				List<String> lis = clazz.getClassInstanceOf(Driver.class,
						targets2);
				for (String s : lis) {
					fCombo.add(s);
					fCombo.setData(s, f);
				}
			}
			for (DatabaseType dType : DatabaseType.INTERNAL_JARS) {
				fCombo.add(dType.getDriverName());
			}
			for (File f : jarFileSet) {
				if (f.exists()
						&& f.getName().toLowerCase().indexOf("ncso.jar") >= 0) { //$NON-NLS-1$
					fCombo.add(DatabaseType.DOMINO.getDriverName());
					fCombo.setData(DatabaseType.DOMINO.getDriverName(), f);
					break;
				}
			}

			comboChange();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	private void comboChange() {
		this.databaseType = DatabaseType.parse(fCombo.getText());

		resetSysCombo();
		resetTab();
		// if (fDisplayNameText.getText().trim().length() == 0) {
		// fDisplayNameText.setText("CON"
		// + PreferenceUtil.getDBInitialItems().length);
		// }
		fUrlOrHostText.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
		fCombo.forceFocus();
		File driverFile = getComboSelectionFile();
		if (driverFile == null) {
			fComboDriverNameLbl.setText("                    "); //$NON-NLS-1$
		} else {
			fComboDriverNameLbl.setText(driverFile.getName());
		}
		resetKeepAliveState();

		this.beforeDatabaseType = this.databaseType;
	}

	private void resetKeepAliveState() {
		if (fKeepAliveIntervalLabel == null) {
			return;
		}
		boolean b = this.databaseType.enableKeepAlive();
		Color color = b ? ColorUtil.getColor(ColorNameEnum.BLACK) : ColorUtil
				.getColor(ColorNameEnum.GRAY);
		fKeepAliveIntervalLabel.setForeground(color);
		fKeepAliveIntervalSpin.setForeground(color);
		fKeepAliveIntervalLabel.setEnabled(b);
		fKeepAliveIntervalSpin.setEnabled(b);

	}

	private void checkAndSetOracleFilter() {
		if (this.databaseType.isOracle()) {
			if (!checked && !initializing && fUserText.getText().length() > 0) {
				matchBtn.setSelection(true);
				ignoreBtn.setSelection(false);
				nothingBtn.setSelection(false);
				fCategoriesRegexText.setText(fUserText.getText());
				fCategoriesRegexText.setEnabled(true);
				checked = true;
			}
		}
	}

	private void resetSysCombo() {
		if (this.databaseType.isOracle()) {
			if (fSysCombo != null) {
				fSysCombo.setEnabled(true);
			}
			if (fCheckDBMSButton != null) {
				fCheckDBMSButton.setVisible(true);
				fCheckDBMSButton.setSelection(true);
			}
			checkAndSetOracleFilter();
		} else {
			if (fSysCombo != null) {
				fSysCombo.setEnabled(false);
				fSysCombo.setText(StringUtil.EMPTY_STRING); //$NON-NLS-1$
			}
			if (fCheckDBMSButton != null) {
				fCheckDBMSButton.setVisible(false);
				fCheckDBMSButton.setSelection(false);
			}
		}

	}

	public String[] listFiles() {
		return null;
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		validate();
	}

	@Override
	public void widgetDefaultSelected(SelectionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void widgetSelected(SelectionEvent arg0) {
		if (arg0.widget == fCombo) {
			comboChange();
		} else if (arg0.widget == nothingBtn || arg0.widget == ignoreBtn
				|| arg0.widget == matchBtn) {
			resetResourceFilterSetting();
		} else {
			resetTab();
		}
	}
}