/*
 *  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 org.apache.openaz.xacml.admin.XacmlAdminUI;
import org.apache.openaz.xacml.admin.jpa.Attribute;
import org.apache.openaz.xacml.admin.jpa.Category;
import org.apache.openaz.xacml.admin.jpa.Datatype;
import org.apache.openaz.xacml.admin.util.JPAUtils;
import org.apache.openaz.xacml.admin.view.events.AttributeChangedEventListener;
import org.apache.openaz.xacml.admin.view.events.AttributeChangedEventNotifier;
import org.apache.openaz.xacml.api.XACML3;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.provider.CachingLocalEntityProvider;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

public class AttributeSimpleCreatorComponent extends CustomComponent implements AttributeChangedEventNotifier {

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

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private HorizontalLayout horizontalLayout_1;
	@AutoGenerated
	private Table tableDatatype;
	@AutoGenerated
	private Table tableCategory;
	@AutoGenerated
	private TextField textFieldContextPath;
	@AutoGenerated
	private TextField textFieldAttributeId;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private final AttributeSimpleCreatorComponent self = this;
	private final Datatype datatype;
	private final Attribute attribute;
	private final BasicNotifier notifier = new BasicNotifier();
	private static final JPAContainer<Category>	categories = new JPAContainer<Category>(Category.class);
	private static final JPAContainer<Datatype>	datatypes = new JPAContainer<Datatype>(Datatype.class);
	static {
		categories.setEntityProvider(new CachingLocalEntityProvider<Category>(Category.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
		datatypes.setEntityProvider(new CachingLocalEntityProvider<Datatype>(Datatype.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
		categories.sort(new String[]{"xacmlId"}, new boolean[]{true});
		datatypes.sort(new String[]{"xacmlId"}, new boolean[]{true});
	}
	/**
	 * 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.
	 */
	public AttributeSimpleCreatorComponent(Datatype datatype, Attribute initialAttribute) {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		//
		// Save
		//
		this.datatype = datatype;
		this.attribute = initialAttribute;
		//
		// Initialize GUI
		//
		this.initializeCategories();
		this.initializeDatatypes();
		this.initializeAttributeId();
		//
		// Focus
		//
		this.textFieldAttributeId.focus();
	}
	
	private void initializeCategories() {
		//
		// Remove any filters
		//
		AttributeSimpleCreatorComponent.categories.removeAllContainerFilters();
		//
		// Initialize data source & GUI properties
		//
		this.tableCategory.setContainerDataSource(AttributeSimpleCreatorComponent.categories);
		this.tableCategory.setVisibleColumns(new Object[] {"xacmlId"});
		this.tableCategory.setColumnHeaders(new String[] {"XACML ID"});
		this.tableCategory.setImmediate(true);
		this.tableCategory.setNullSelectionAllowed(false);
		this.tableCategory.setPageLength(10);
		this.tableCategory.setSelectable(true);
		//
		// Default selection
		//
		Category defaultCategory;
		if (this.attribute == null || this.attribute.getCategoryBean() == null || this.attribute.getCategoryBean().getIdentifer() == null) {
			defaultCategory = JPAUtils.findCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT);
			assert defaultCategory != null;
		} else {
			defaultCategory = JPAUtils.findCategory(this.attribute.getCategoryBean().getIdentifer());
		}
		if (defaultCategory != null) {
			this.tableCategory.select(defaultCategory.getId());
		}
		//
		// Respond to changes
		//
		this.tableCategory.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.fireAttributeChanged(self.getAttribute());
			}
		});
	}

	private void initializeDatatypes() {
		//
		// Remove any filters
		//
		AttributeSimpleCreatorComponent.datatypes.removeAllContainerFilters();
		//
		// Initialize data source & GUI properties
		//
		this.tableDatatype.setContainerDataSource(AttributeSimpleCreatorComponent.datatypes);
		this.tableDatatype.setVisibleColumns(new Object[] {"xacmlId", "shortName"});
		this.tableDatatype.setColumnHeaders(new String[] {"Data Type ID", "Data Type"});
		this.tableDatatype.setNullSelectionAllowed(false);
		this.tableDatatype.setImmediate(true);
		this.tableDatatype.setPageLength(10);
		//
		// Are we restricted to a certain datatype?
		//
		if (this.datatype != null) {
			//
			// Datatype restricted
			//
			this.tableDatatype.select(this.datatype.getId());
			this.tableDatatype.setEnabled(false);
			return;
		}
		this.tableDatatype.setSelectable(true);
		//
		// Do we have a default value?
		//
		Datatype defaultDatatype;
		if (this.attribute != null && this.attribute.getDatatypeBean() != null) {
			defaultDatatype = this.attribute.getDatatypeBean();
		} else {
			defaultDatatype = JPAUtils.findDatatype(XACML3.ID_DATATYPE_STRING);
		}
		if (defaultDatatype != null) {
			this.tableDatatype.select(defaultDatatype.getId());
		}
		//
		// Respond to changes
		//
		this.tableDatatype.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.fireAttributeChanged(self.getAttribute());
			}
		});
	}
	
	private void initializeAttributeId() {
		this.textFieldAttributeId.setImmediate(true);
		this.textFieldAttributeId.setNullRepresentation("");
		if (this.attribute == null) {
			this.textFieldAttributeId.setValue(XacmlAdminUI.getDomain());
		} else {
			//
			// Set the ID
			//
			this.textFieldAttributeId.setValue(this.attribute.getXacmlId());
			//
			// Is it an attribute selector?
			//
			if (this.attribute.isDesignator()) {
				this.textFieldContextPath.setVisible(false);
				this.textFieldContextPath.setRequired(false);
			} else {
				this.textFieldAttributeId.setCaption("Context Selector Id");
				this.textFieldAttributeId.setRequired(false);
				this.textFieldContextPath.setVisible(true);				
				this.textFieldContextPath.setValue(this.attribute.getSelectorPath());
				this.textFieldContextPath.setRequired(true);
				this.textFieldContextPath.setRequiredError("You must have a context path for a selector.");
				this.textFieldContextPath.addValueChangeListener(new ValueChangeListener() {
					private static final long serialVersionUID = 1L;

					@Override
					public void valueChange(ValueChangeEvent event) {
						self.fireAttributeChanged(self.getAttribute());
					}
				});
			}
		}
		//
		// Respond to changes
		//
		this.textFieldAttributeId.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.fireAttributeChanged(self.getAttribute());
			}
		});
	}
	
	@Override
	public Attribute	getAttribute() {
		try {
			this.textFieldAttributeId.commit();
		} catch (Exception e) { //NOPMD
			// TODO - Handle, Log or NOPMD
			// TODO - Will vaadin display error?
		}
		Attribute attribute = new Attribute(this.textFieldAttributeId.getValue());
		attribute.setSelectorPath(this.textFieldContextPath.getValue());
		Object categoryId = this.tableCategory.getValue();
		if (categoryId != null) {
			attribute.setCategoryBean(AttributeSimpleCreatorComponent.categories.getItem(categoryId).getEntity());
		}
		if (this.datatype != null) {
			attribute.setDatatypeBean(this.datatype);
		} else {
			Object datatypeId = this.tableDatatype.getValue();
			if (datatypeId == null) {
				return null;
			}
			attribute.setDatatypeBean(AttributeSimpleCreatorComponent.datatypes.getItem(datatypeId).getEntity());
		}
		return attribute;
	}
	
	@Override
	public boolean addListener(AttributeChangedEventListener listener) {
		return this.notifier.addListener(listener);
	}

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

	@Override
	public void commit() {
		try {
			this.textFieldAttributeId.commit();
			this.textFieldContextPath.commit();
			this.tableCategory.commit();
			this.tableDatatype.commit();
		} catch (Exception e) { //NOPMD
			// TODO - Handle, Log or NOPMD
			// TODO - Will vaadin display error?
		}
	}

	@Override
	public void fireAttributeChanged(Attribute attribute) {
		this.notifier.fireAttributeChanged(attribute);
	}

	@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");
		
		// textFieldAttributeId
		textFieldAttributeId = new TextField();
		textFieldAttributeId.setCaption("Attribute Id");
		textFieldAttributeId.setImmediate(false);
		textFieldAttributeId.setWidth("100.0%");
		textFieldAttributeId.setHeight("-1px");
		textFieldAttributeId.setInvalidAllowed(false);
		textFieldAttributeId.setRequired(true);
		mainLayout.addComponent(textFieldAttributeId);
		mainLayout.setExpandRatio(textFieldAttributeId, 1.0f);
		
		// textFieldContextPath
		textFieldContextPath = new TextField();
		textFieldContextPath.setCaption("Context Path");
		textFieldContextPath.setImmediate(false);
		textFieldContextPath.setDescription("The Selector's Context Path.");
		textFieldContextPath.setWidth("100.0%");
		textFieldContextPath.setHeight("-1px");
		textFieldContextPath
				.setInputPrompt("eg. md:record/md:patient/md:patient-number/text()");
		mainLayout.addComponent(textFieldContextPath);
		mainLayout.setExpandRatio(textFieldContextPath, 1.0f);
		
		// horizontalLayout_1
		horizontalLayout_1 = buildHorizontalLayout_1();
		mainLayout.addComponent(horizontalLayout_1);
		mainLayout.setExpandRatio(horizontalLayout_1, 1.0f);
		
		return mainLayout;
	}

	@AutoGenerated
	private HorizontalLayout buildHorizontalLayout_1() {
		// common part: create layout
		horizontalLayout_1 = new HorizontalLayout();
		horizontalLayout_1.setImmediate(false);
		horizontalLayout_1.setWidth("-1px");
		horizontalLayout_1.setHeight("-1px");
		horizontalLayout_1.setMargin(false);
		horizontalLayout_1.setSpacing(true);
		
		// tableCategory
		tableCategory = new Table();
		tableCategory.setCaption("Choose Category");
		tableCategory.setImmediate(false);
		tableCategory.setWidth("-1px");
		tableCategory.setHeight("-1px");
		tableCategory.setInvalidAllowed(false);
		tableCategory.setRequired(true);
		horizontalLayout_1.addComponent(tableCategory);
		
		// tableDatatype
		tableDatatype = new Table();
		tableDatatype.setCaption("Choose Data Type");
		tableDatatype.setImmediate(false);
		tableDatatype.setWidth("-1px");
		tableDatatype.setHeight("-1px");
		tableDatatype.setInvalidAllowed(false);
		tableDatatype.setRequired(true);
		horizontalLayout_1.addComponent(tableDatatype);
		
		return horizontalLayout_1;
	}

}
