/*
 * 作成日: 2008/08/05
 * 著作権: Copyright (c) 2005 ZIGEN
 * ライセンス：Eclipse Public License - v 1.0
 * 原文：http://www.eclipse.org/legal/epl-v10.html
 */
package zigen.plugin.db.ext.s2jdbc.wizards;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import zigen.plugin.db.DbPlugin;
import zigen.plugin.db.core.IDBConfig;
import zigen.plugin.db.ui.actions.AutoDelayListener;
import zigen.plugin.db.ui.internal.DataBase;
import zigen.plugin.db.ui.internal.Folder;
import zigen.plugin.db.ui.internal.ITable;
import zigen.plugin.db.ui.internal.Schema;
import zigen.plugin.db.ui.internal.TreeLeaf;
import zigen.plugin.db.ui.internal.TreeNode;
import zigen.plugin.db.ui.views.TreeLabelProvider;
import zigen.plugin.db.ui.views.TreeViewListener;
import zigen.plugin.db.ui.views.TreeViewSchemaFilter;
import zigen.plugin.db.ui.views.TreeViewSorter;
import zigen.plugin.db.ui.views.internal.TableFilter;


public class SelectTableDialog extends Dialog {
	
	public static final int BUTTON_WIDTH = 100;
	
	public static final int HORIZONTAL_SPACING = 3;
	
	public static final int MARGIN_WIDTH = 0;
	
	public static final int MARGIN_HEIGHT = 2;
	
	protected TreeViewer viewer;
	
	protected IDBConfig config;
	
	protected DataBase db;
	
	protected ITable table;
	
	protected TableFilter fTableFilter;
	
	protected Text searchText;
	
	private class TableSelectContentProvider implements ITreeContentProvider {
		
		public TableSelectContentProvider() {}
		
		public Object[] getElements(Object inputElement) {
			List folders = null;
			
			if (db.isSchemaSupport()) {
				List schema = db.getChildren();
				for (Iterator iter = schema.iterator(); iter.hasNext();) {
					Schema s = (Schema) iter.next();
					if (s.getName().equalsIgnoreCase(db.getDefaultSchema())) {
						folders = s.getChildren();
						break;
					}
					
				}
				
			} else {
				folders = db.getChildren();
			}
			
			for (Iterator iter = folders.iterator(); iter.hasNext();) {
				Folder f = (Folder) iter.next();
				if ("TABLE".equalsIgnoreCase(f.getName())) { //$NON-NLS-1$
					return getChildren(f);
				}
				
			}
			return null;
			
		}
		
		public Object getParent(Object element) {
			if (element instanceof TreeLeaf) {
				return ((TreeLeaf) element).getParent();
			}
			return null;
		}
		
		public Object[] getChildren(Object parentElement) {
			if (parentElement instanceof TreeNode) {
				return ((TreeNode) parentElement).getChildrens();
			}
			return new Object[0];
		}
		
		public boolean hasChildren(Object element) {
			if (element instanceof TreeNode)
				return ((TreeNode) element).hasChildren();
			return false;
		}
		
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
		
		public void dispose() {}
		
	}
	
	private class TreeDoubleClickHandler implements IDoubleClickListener {
		
		private boolean showDialog = false;
		
		public void doubleClick(DoubleClickEvent event) {
			
			try {
				
				Viewer view = event.getViewer();
				ISelection selection = event.getSelection();
				if (view instanceof TreeViewer && selection instanceof StructuredSelection) {
					TreeViewer viewer = (TreeViewer) view;
					Object element = ((StructuredSelection) selection).getFirstElement();
					if (element instanceof ITable) {
						close();
					}
				}
			} catch (Exception e) {
				DbPlugin.log(e);
			}
			
		}
		
	}
	
	private class AutoDelayFiltertListener extends AutoDelayListener {
		
		private static final int delayTime = 300;
		
		public AutoDelayFiltertListener() {
			super(delayTime);
		}
		
		public Runnable createExecutAction() {
			return new Runnable() {
				
				public void run() {
					try {
						String condition = searchText.getText();
						if (fTableFilter != null)
							viewer.removeFilter(fTableFilter);
						fTableFilter = new TableFilter(condition);
						viewer.addFilter(fTableFilter);
					} catch (Exception e) {
						DbPlugin.log(e);
					}
				}
			};
		}
	}
	
	public SelectTableDialog(Shell parent, DataBase db) {
		super(parent);
		this.db = db;
		if (db != null)
			this.config = db.getDbConfig();
	}
	
	protected void okPressed() {
		if (save()) {
			super.okPressed();
		}
	}
	
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText(Messages.getString("SelectTableDialog.1")); //$NON-NLS-1$
	}
	
	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);
		GridLayout layout = new GridLayout(1, false);
		composite.setLayout(layout);
		createSearch(composite);
		createList(composite);
		// セパレータ(parentに対して定義する)
		addSeparator(parent);
		return composite;
	}
	
	private void createSearch(Composite composite) {
		searchText = new Text(composite, SWT.BORDER);
		GridData data = new GridData(GridData.FILL_BOTH);
		searchText.setLayoutData(data);
		searchText.addKeyListener(new AutoDelayFiltertListener());
		
	}
	
	private void createList(Composite composite) {
		
		viewer = new TreeViewer(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE);
		// viewer.addFilter(new TableFilter());
		viewer.setContentProvider(new TableSelectContentProvider());
		viewer.setLabelProvider(new TreeLabelProvider());
		viewer.setSorter(new TreeViewSorter());
		viewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
		viewer.expandToLevel(1);
		
		// Listenerの追加(スキーマ展開時にテーブルを検索する）
		viewer.addTreeListener(new TreeViewListener());
		
		// 表示スキーマを設定する
		viewer.addFilter(new TreeViewSchemaFilter(config.getDisplayedSchemas()));
		
		GridData data = new GridData(GridData.FILL_BOTH);
		data.verticalSpan = 4;
		data.widthHint = 300;
		data.heightHint = viewer.getTree().getItemHeight() * 10;
		viewer.getTree().setLayoutData(data);
		
		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
			
			public void selectionChanged(SelectionChangedEvent event) {
				tableSelectionChangedHandler(event);
			}
		});
		
		viewer.addDoubleClickListener(new TreeDoubleClickHandler());
		
	}
	
	protected void tableSelectionChangedHandler(SelectionChangedEvent event) {
		Object element = (Object) ((IStructuredSelection) event.getSelection()).getFirstElement();
		if (element instanceof ITable) {
			table = (ITable) element;
		} else {
			table = null;
		}
		
	}
	
	private void addSeparator(Composite parent) {
		Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
		GridData gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.grabExcessHorizontalSpace = true;
		separator.setLayoutData(gridData);
	}
	
	private boolean save() {
		try {
			Object element = (Object) ((StructuredSelection) viewer.getSelection()).getFirstElement();
			if (element instanceof ITable) {
				table = (ITable) element;
			} else {
				table = null;
			}
			return true;
			
		} catch (Exception e) {
			DbPlugin.getDefault().showErrorDialog(e);
		}
		return false;
	}
	
	private TreeNode selectedNode = null;
	
	public TreeNode getSelectedNode() {
		return selectedNode;
	}
	
	
	/**
	 * @return the table
	 */
	public ITable getTable() {
		return table;
	}
	
}
