/*
 * Created on 05.07.2004
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 */
package networkconsole.datamodel.swt.dialogs;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.ResourceBundle;

import networkconsole.datamodel.LdapEntry;
import networkconsole.datamodel.LdapEntryList;
import networkconsole.datamodel.LdapEntryReflector;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * @author Eugene Prokopiev <john@rmts.donpac.ru>
 * 
 */
public class EntryDialog extends Dialog {

	private LdapEntryList list;
	private LdapEntry entry;
	private LdapEntryReflector reflector;
	
	private ArrayList editControls = new ArrayList();
	
	public EntryDialog(Shell parent, LdapEntryList list, LdapEntry entry) {
		super(parent);
		this.list = list;
		this.entry = entry;
		this.reflector = new LdapEntryReflector(list.getEntryClass());
	}
	
	protected Control createDialogArea(Composite parent) {
		Composite area = (Composite) super.createDialogArea(parent);
		Composite container = new Composite(area, SWT.NONE);
		container.setLayout(new FormLayout());
		GridData gridData = new GridData(GridData.FILL_BOTH);
		gridData.widthHint = 500;
		container.setLayoutData(gridData);
		{
			final Composite composite = new Composite(container, SWT.NONE);
			composite.setLayout(new GridLayout());
			final FormData formData = new FormData();
			formData.bottom = new FormAttachment(100, 5);
			formData.right = new FormAttachment(100, 5);
			formData.top = new FormAttachment(0, -5);
			formData.left = new FormAttachment(0, -5);
			composite.setLayoutData(formData);
			{
				final Group group = new Group(composite, SWT.NONE);
				group.setLayoutData(new GridData(GridData.FILL_BOTH));
				final GridLayout gridLayout = new GridLayout();
				gridLayout.numColumns = 2;
				gridLayout.marginWidth = 7;
				gridLayout.marginHeight = 7;
				gridLayout.horizontalSpacing = 15;
				group.setLayout(gridLayout);	
				
				createEntryEditor(group);
			}
		}
		
		return area;
	}
	
	private void createEntryEditor(final Group group) {
		
		for (int i=0; i<reflector.getDescribeMethods().size(); i++) {			
			try {
				
				final Label label = new Label(group, SWT.NONE);
				String methodName = reflector.getDescribeMethods().get(i).toString();
				String columnName = "";
				columnName = reflector.invokeMethod(null, methodName);	
				label.setText(columnName);
				
				String getterMethodName = reflector.getGetterMethods().get(i).toString();
				if (getterMethodName.startsWith("get")) {
					final Text text = new Text(group, SWT.BORDER);
					editControls.add(text);
					text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
					if (entry != null)
						text.setText(reflector.invokeMethod(entry, getterMethodName));						
				} else if (getterMethodName.startsWith("is")) {
					final Button check = new Button(group, SWT.CHECK);
					editControls.add(check);
					if (entry != null)
						check.setSelection((reflector.invokeMethod(entry, getterMethodName) == "true")?(true):(false));
				} else {
					final Composite empty = new Composite(group, SWT.NONE);
					editControls.add(empty);
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (reflector.getDescribeMethods().size() > 0 && entry != null)
			((Control)editControls.get(0)).setEnabled(false);
	}

	protected void createButtonsForButtonBar(Composite parent) {
		
		createButton(
			parent,
			IDialogConstants.OK_ID,
			translate("ui.dialog.ok"),
			true);
			
		createButton(
			parent,
			IDialogConstants.CANCEL_ID,
			translate("ui.dialog.cancel"),
			false);
	}
	
	protected void okPressed() {
		try {			
			if (entry == null)
				addEntry();
			else
				editEntry();
			super.okPressed();
		} catch (Exception e) {
			MessageDialog.openError(getShell(), getShell().getText(), 
				"["+e.getClass().getName()+"] "+e.getLocalizedMessage());
			e.printStackTrace();
		}						
	}
	
	protected void addEntry() throws Exception {
		try {
			Constructor[] constructors = list.getEntryClass().getDeclaredConstructors();
			String arg = ((Text)editControls.get(0)).getText();
			entry = (LdapEntry)constructors[0].newInstance(new Object[] {arg});
			fillEntryFields();
			list.add(entry);
		} finally {
			entry = null;
		}
	}
	
	private void fillEntryFields() throws IOException {
		for (int i=1; i<editControls.size(); i++) {
			Object method = reflector.getSetterMethods().get(i);
			if (method != null) {
				String methodName = method.toString();
				Object param = methodParam(i, methodName);
				reflector.invokeMethod(entry, methodName, param);
			}
		}
	}

	private Object methodParam(int index, String methodName) throws IOException {
		if (editControls.get(index) instanceof Text) {
			return ((Text)editControls.get(index)).getText();
		} else if (editControls.get(index) instanceof Button) {
			return new Boolean(((Button)editControls.get(index)).getSelection());
		} else {
			return null;
		}
	}

	protected void editEntry() throws Exception {
		fillEntryFields();
	}

	protected void configureShell(Shell shell) {		
		super.configureShell(shell);
		shell.setText(translate("ui.dialog.entry.caption"));
	}
	
	public static String translate(String element) {
		return ResourceBundle.getBundle("networkconsole/datamodel/swt/dialogs/translation").getString(element);
	}

}
