/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */

package org.apache.openaz.xacml.admin.view.components;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.openaz.xacml.admin.jpa.PIPConfigParam;
import org.apache.openaz.xacml.admin.jpa.PIPConfiguration;
import org.apache.openaz.xacml.admin.view.events.FormChangedEventListener;
import org.apache.openaz.xacml.admin.view.events.FormChangedEventNotifier;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Buffered.SourceException;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.server.Page;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Notification.Type;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

public class LDAPPIPConfigurationComponent extends CustomComponent implements FormChangedEventNotifier {
	
	@AutoGenerated
	private VerticalLayout mainLayout;

	@AutoGenerated
	private Button buttonTest;

	@AutoGenerated
	private TextField textFieldScope;

	@AutoGenerated
	private TextField textFieldCredentials;

	@AutoGenerated
	private TextField textFieldPrincipal;

	@AutoGenerated
	private ComboBox comboBoxAuthentication;

	@AutoGenerated
	private TextField textFieldProviderURL;

	@AutoGenerated
	private TextField textFieldFactory;

	public static String CLASSNAME = "org.apache.openaz.xacml.std.pip.engines.ldap.LDAPEngine";
	
	public static String LDAP_CONTEXT = Context.INITIAL_CONTEXT_FACTORY;
	public static String LDAP_URL = Context.PROVIDER_URL;
	public static String LDAP_AUTH = "authentication";
	public static String LDAP_PRINCIPAL = "principal";
	public static String LDAP_CREDENTIALS = "credentials";
	public static String LDAP_SCOPE = "scope";
	
	public static String LDAP_DEFAULT_CONTEXT = "com.sun.jndi.ldap.LdapCtxFactory";
	
	public static String LDAP_AUTH_ANONYMOUS = "anonymous";
	public static String LDAP_AUTH_SIMPLE = "simple";
	public static String LDAP_AUTH_SASL = "SASL";	//????

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final Log logger	= LogFactory.getLog(LDAPPIPConfigurationComponent.class);
	private final LDAPPIPConfigurationComponent self = this;
	private final BasicNotifier notifier = new BasicNotifier();
	private final EntityItem<PIPConfiguration> entity;
	/**
	 * The constructor should first build the main layout, set the
	 * composition root and then do any custom initialization.
	 *
	 * The constructor will not be automatically regenerated by the
	 * visual editor.
	 * @param configParamField 
	 */
	public LDAPPIPConfigurationComponent(EntityItem<PIPConfiguration> entity) {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		//
		// Save
		//
		this.entity = entity;
		//
		// Initialize
		//
		this.initialize();
	}
	
	protected void initialize() {
		if (logger.isDebugEnabled()) {
			logger.debug("initializing " + this.entity.getEntity().toString());
		}
		//
		// Iterate any existing values
		//
		Set<PIPConfigParam> unneeded = new HashSet<PIPConfigParam>();
		for (PIPConfigParam param : this.entity.getEntity().getPipconfigParams()) {
			if (param.getParamName().equals(LDAP_CONTEXT)) {
				this.textFieldFactory.setData(param);
			} else if (param.getParamName().equals(LDAP_URL)) {
				this.textFieldProviderURL.setData(param);
			} else if (param.getParamName().equals(LDAP_AUTH)) {
				this.comboBoxAuthentication.setData(param);
			} else if (param.getParamName().equals(LDAP_PRINCIPAL)) {
				this.textFieldPrincipal.setData(param);
			} else if (param.getParamName().equals(LDAP_CREDENTIALS)) {
				this.textFieldCredentials.setData(param);
			} else if (param.getParamName().equals(LDAP_SCOPE)) {
				this.textFieldScope.setData(param);
			} else {
				unneeded.add(param);
			}
		}
		//
		// Get rid of unneeded parameters
		//
		if (unneeded.isEmpty() == false) {
			this.entity.getEntity().getPipconfigParams().removeAll(unneeded);
		}
		//
		// Initialize GUI
		//
		this.initializeEntity();
		this.initializeCombo();
		this.initializeText();
		this.initializeButtons();
	}
	
	protected void initializeEntity() {
		//
		// Initialize the entity
		//
		this.entity.getEntity().setClassname(CLASSNAME);
		this.entity.getEntity().setRequiresResolvers(true);
	}
	
	protected void initializeCombo() {
		//
		// GUI properties
		//
		this.comboBoxAuthentication.setImmediate(true);
		this.comboBoxAuthentication.setNullSelectionAllowed(false);
		this.comboBoxAuthentication.setRequired(true);
		this.comboBoxAuthentication.setRequiredError("You must select an authentication mechanism");
		//
		// Initial set of items
		//
		this.comboBoxAuthentication.addItem(LDAP_AUTH_ANONYMOUS);
		this.comboBoxAuthentication.addItem(LDAP_AUTH_SIMPLE);
		this.comboBoxAuthentication.addItem(LDAP_AUTH_SASL);
		//
		// Ensure the authentication combo is selected to something.
		//
		PIPConfigParam param = (PIPConfigParam) this.comboBoxAuthentication.getData();
		if (param == null) {
			param = new PIPConfigParam(LDAP_AUTH, LDAP_AUTH_ANONYMOUS);
			this.entity.getEntity().addPipconfigParam(param);
			this.comboBoxAuthentication.setData(param);
			this.comboBoxAuthentication.select(param.getParamValue());
		} else {
			//
			// Is this custom?
			//
			this.comboBoxAuthentication.select(param.getParamValue());
			if (this.comboBoxAuthentication.getValue().equals(param.getParamValue()) == false) {
				this.comboBoxAuthentication.addItem(param.getParamValue());
				this.comboBoxAuthentication.select(param.getParamValue());
			}
		}
		//
		// Respond to events
		//
		this.comboBoxAuthentication.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.comboBoxAuthentication.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_AUTH, self.comboBoxAuthentication.getValue().toString());
					self.entity.getEntity().addPipconfigParam(param);
					self.comboBoxAuthentication.setData(param);
				}
				param.setParamValue(self.comboBoxAuthentication.getValue().toString());
				self.fireFormChangedEvent();
			}		
		});
	}
	
	protected void initializeText() {
		//
		//
		//
		this.textFieldFactory.setImmediate(true);
		this.textFieldFactory.setNullRepresentation("");
		//
		// We can initialize this if there is no value
		//
		PIPConfigParam param = (PIPConfigParam) this.textFieldFactory.getData();
		if (param == null) {
			param = new PIPConfigParam(LDAP_CONTEXT, LDAP_DEFAULT_CONTEXT);
			this.entity.getEntity().addPipconfigParam(param);
			this.textFieldFactory.setData(param);
		}
		this.textFieldFactory.setValue(param.getParamValue());
		this.textFieldFactory.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldFactory.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_CONTEXT);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldFactory.setData(param);
				}
				param.setParamValue(self.textFieldFactory.getValue());
				self.fireFormChangedEvent();
			}
		});
		this.textFieldFactory.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldFactory.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_CONTEXT);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldFactory.setData(param);
				}
				param.setParamValue(self.textFieldFactory.getValue());
				self.fireFormChangedEvent();
			}
		});
		//
		//
		//
		this.textFieldProviderURL.setImmediate(true);
		this.textFieldProviderURL.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldProviderURL.getData();
		if (param != null) {
			this.textFieldProviderURL.setValue(param.getParamValue());
		}		
		this.textFieldProviderURL.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldProviderURL.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_URL);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldProviderURL.setData(param);
				}
				param.setParamValue(self.textFieldProviderURL.getValue());
				self.fireFormChangedEvent();
			}			
		});
		this.textFieldProviderURL.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldProviderURL.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_URL);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldProviderURL.setData(param);
				}
				param.setParamValue(self.textFieldProviderURL.getValue());
				self.fireFormChangedEvent();
			}			
		});
		//
		//
		//
		this.textFieldPrincipal.setImmediate(true);
		this.textFieldPrincipal.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldPrincipal.getData();
		if (param != null) {
			this.textFieldPrincipal.setValue(param.getParamValue());
		}		
		this.textFieldPrincipal.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldPrincipal.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_PRINCIPAL);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldPrincipal.setData(param);
				}
				param.setParamValue(self.textFieldPrincipal.getValue());
				self.fireFormChangedEvent();
			}			
		});
		this.textFieldPrincipal.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldPrincipal.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_PRINCIPAL);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldPrincipal.setData(param);
				}
				param.setParamValue(self.textFieldPrincipal.getValue());
				self.fireFormChangedEvent();
			}			
		});
		//
		//
		//
		this.textFieldCredentials.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldCredentials.getData();
		if (param != null) {
			this.textFieldCredentials.setValue(param.getParamValue());
		}		
		this.textFieldCredentials.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldCredentials.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_CREDENTIALS);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldCredentials.setData(param);
				}
				param.setParamValue(self.textFieldCredentials.getValue());
				self.fireFormChangedEvent();
			}			
		});
		this.textFieldCredentials.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldCredentials.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_CREDENTIALS);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldCredentials.setData(param);
				}
				param.setParamValue(self.textFieldCredentials.getValue());
				self.fireFormChangedEvent();
			}			
		});
		//
		//
		//
		this.textFieldScope.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldScope.getData();
		if (param == null) {
			param = new PIPConfigParam(LDAP_SCOPE, "subtree");
			this.entity.getEntity().addPipconfigParam(param);
			this.textFieldScope.setData(param);
		}
		this.textFieldScope.setValue(param.getParamValue());
		this.textFieldScope.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldScope.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_SCOPE);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldScope.setData(param);
				}
				param.setParamValue(self.textFieldScope.getValue());
				self.fireFormChangedEvent();
			}			
		});
		this.textFieldScope.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldScope.getData();
				if (param == null) {
					param = new PIPConfigParam(LDAP_SCOPE);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldScope.setData(param);
				}
				param.setParamValue(self.textFieldScope.getValue());
				self.fireFormChangedEvent();
			}			
		});
	}
	
	protected void initializeButtons() {
		this.buttonTest.setImmediate(true);
		this.buttonTest.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				self.testLDAPConnection();
			}
		});
	}
	
	protected void testLDAPConnection() {
		Hashtable<String, String> env = new Hashtable<String, String>();
		env.put(Context.INITIAL_CONTEXT_FACTORY, this.textFieldFactory.getValue());
		env.put(Context.PROVIDER_URL, this.textFieldProviderURL.getValue());
		env.put(Context.SECURITY_PRINCIPAL, this.textFieldPrincipal.getValue());
		env.put(Context.SECURITY_CREDENTIALS, this.textFieldCredentials.getValue());

		String auth = this.comboBoxAuthentication.getValue().toString();
		env.put(Context.SECURITY_AUTHENTICATION, auth);
		//
		// Do we need to do anything?
		//
		/*
		if (auth.equals(LDAP_AUTH_ANONYMOUS)) {
			
		} else if (auth.equals(LDAP_AUTH_SIMPLE)) {
			
		} else if (auth.equals(LDAP_AUTH_SASL)) {
			
		}
		*/

		DirContext ctx = null;
		try {
		   ctx = new InitialDirContext(env);
			new Notification("Success!",
				    "Connection Established!",
				    Type.HUMANIZED_MESSAGE, true)
				    .show(Page.getCurrent());			
		} catch (NamingException e) {
		   logger.error(e);
			new Notification("Connection Failed",
				    "<br/>" + e.getLocalizedMessage(),
				    Type.ERROR_MESSAGE, true)
				    .show(Page.getCurrent());
		} finally {
			try {
				if (ctx != null) {
					ctx.close();
				}
			} catch (NamingException idontcare) { //NOPMD
			}
		}
	}
	
	public void validate() throws InvalidValueException {
		if (logger.isDebugEnabled()) {
			logger.debug("validate");
		}
		this.comboBoxAuthentication.validate();
		this.textFieldFactory.validate();
		this.textFieldProviderURL.validate();
		this.textFieldPrincipal.validate();
		this.textFieldCredentials.validate();
		this.textFieldScope.validate();
	}

	public void commit() throws SourceException, InvalidValueException {
		if (logger.isDebugEnabled()) {
			logger.debug("commit");
		}
		this.comboBoxAuthentication.commit();
		this.textFieldFactory.commit();
		this.textFieldProviderURL.commit();
		this.textFieldPrincipal.commit();
		this.textFieldCredentials.commit();
		this.textFieldScope.commit();
	}
	
	public void discard() throws SourceException {
		if (logger.isDebugEnabled()) {
			logger.debug("discard");
		}
		
		this.textFieldFactory.discard();
		this.textFieldProviderURL.discard();
		this.textFieldPrincipal.discard();
		this.textFieldCredentials.discard();
		this.textFieldScope.discard();
		/*
		this.entity.getEntity().getPipconfigParams().remove(LDAP_CONTEXT);
		this.entity.getEntity().getPipconfigParams().remove(LDAP_URL);
		this.entity.getEntity().getPipconfigParams().remove(LDAP_AUTH);
		this.entity.getEntity().getPipconfigParams().remove(LDAP_PRINCIPAL);
		this.entity.getEntity().getPipconfigParams().remove(LDAP_CREDENTIALS);
		this.entity.getEntity().getPipconfigParams().remove(LDAP_SCOPE);
		*/
	}

	@Override
	public boolean addListener(FormChangedEventListener listener) {
		return this.notifier.addListener(listener);
	}

	@Override
	public boolean removeListener(FormChangedEventListener listener) {
		return this.notifier.removeListener(listener);
	}

	@Override
	public void fireFormChangedEvent() {
		this.notifier.fireFormChangedEvent();
	}
	
	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("-1px");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(true);
		mainLayout.setSpacing(true);
		
		// top-level component properties
		setWidth("-1px");
		setHeight("-1px");
		
		// textFieldFactory
		textFieldFactory = new TextField();
		textFieldFactory.setCaption("Initial Context Factory");
		textFieldFactory.setImmediate(false);
		textFieldFactory.setWidth("-1px");
		textFieldFactory.setHeight("-1px");
		textFieldFactory.setInvalidAllowed(false);
		textFieldFactory.setRequired(true);
		textFieldFactory.setInputPrompt("com.sun.jndi.ldap.LdapCtxFactory");
		mainLayout.addComponent(textFieldFactory);
		mainLayout.setExpandRatio(textFieldFactory, 1.0f);
		
		// textFieldProviderURL
		textFieldProviderURL = new TextField();
		textFieldProviderURL.setCaption("Provider URL");
		textFieldProviderURL.setImmediate(false);
		textFieldProviderURL.setWidth("-1px");
		textFieldProviderURL.setHeight("-1px");
		textFieldProviderURL.setInvalidAllowed(false);
		textFieldProviderURL.setRequired(true);
		textFieldProviderURL
				.setInputPrompt("Eg. ldap://localhost:389/o=JNDITutorial");
		mainLayout.addComponent(textFieldProviderURL);
		mainLayout.setExpandRatio(textFieldProviderURL, 1.0f);
		
		// comboBoxAuthentication
		comboBoxAuthentication = new ComboBox();
		comboBoxAuthentication.setCaption("Authentication");
		comboBoxAuthentication.setImmediate(false);
		comboBoxAuthentication.setWidth("-1px");
		comboBoxAuthentication.setHeight("-1px");
		comboBoxAuthentication.setRequired(true);
		mainLayout.addComponent(comboBoxAuthentication);
		mainLayout.setExpandRatio(comboBoxAuthentication, 1.0f);
		
		// textFieldPrincipal
		textFieldPrincipal = new TextField();
		textFieldPrincipal.setCaption("Principal");
		textFieldPrincipal.setImmediate(false);
		textFieldPrincipal.setWidth("-1px");
		textFieldPrincipal.setHeight("-1px");
		textFieldPrincipal.setNullSettingAllowed(true);
		mainLayout.addComponent(textFieldPrincipal);
		mainLayout.setExpandRatio(textFieldPrincipal, 1.0f);
		
		// textFieldCredentials
		textFieldCredentials = new TextField();
		textFieldCredentials.setCaption("Credentials");
		textFieldCredentials.setImmediate(false);
		textFieldCredentials.setWidth("-1px");
		textFieldCredentials.setHeight("-1px");
		textFieldCredentials.setNullSettingAllowed(true);
		mainLayout.addComponent(textFieldCredentials);
		mainLayout.setExpandRatio(textFieldCredentials, 1.0f);
		
		// textFieldScope
		textFieldScope = new TextField();
		textFieldScope.setCaption("Scope");
		textFieldScope.setImmediate(false);
		textFieldScope.setWidth("-1px");
		textFieldScope.setHeight("-1px");
		textFieldScope.setInvalidAllowed(false);
		textFieldScope.setRequired(true);
		textFieldScope.setInputPrompt("Eg. subtree");
		mainLayout.addComponent(textFieldScope);
		
		// buttonTest
		buttonTest = new Button();
		buttonTest.setCaption("Test Connection");
		buttonTest.setImmediate(true);
		buttonTest.setWidth("-1px");
		buttonTest.setHeight("-1px");
		mainLayout.addComponent(buttonTest);
		mainLayout.setComponentAlignment(buttonTest, new Alignment(48));
		
		return mainLayout;
	}
}
