/*
 *  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.windows;

import java.util.List;
import java.util.Map;

import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;

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

import org.apache.openaz.xacml.admin.XacmlAdminUI;
import org.apache.openaz.xacml.admin.jpa.Datatype;
import org.apache.openaz.xacml.admin.jpa.FunctionArgument;
import org.apache.openaz.xacml.admin.jpa.FunctionDefinition;
import org.apache.openaz.xacml.admin.util.JPAUtils;
import org.apache.openaz.xacml.admin.view.events.ApplyParametersChangedListener;
import org.apache.openaz.xacml.admin.view.events.ApplyParametersChangedNotifier;
import org.apache.openaz.xacml.api.XACML3;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Buffered.SourceException;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Filter;
import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.data.util.filter.SimpleStringFilter;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
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.CheckBox;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class ApplyEditorWindow extends Window implements ApplyParametersChangedNotifier {

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

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Button buttonSelect;
	@AutoGenerated
	private Table tableFunction;
	@AutoGenerated
	private HorizontalLayout horizontalLayout_1;
	@AutoGenerated
	private CheckBox checkBoxFilterIsBag;
	@AutoGenerated
	private ComboBox comboBoxDatatypeFilter;
	@AutoGenerated
	private TextField textFieldFilter;
	@AutoGenerated
	private TextArea textAreaDescription;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Log logger	= LogFactory.getLog(ApplyEditorWindow.class);
	private final ApplyEditorWindow self = this;
	private final ApplyParametersChangedNotifier notifier = new ApplyParametersChangedNotifier.BasicNotifier();
	private final BeanItemContainer<FunctionDefinition>	container = new BeanItemContainer<FunctionDefinition>(FunctionDefinition.class);
	private final ApplyType apply;
	private final ApplyType applyParent;
	private final FunctionArgument argument;
	private final Object parent;
	private boolean isSaved = false;
	private FunctionDefinition function = null;
	/**
	 * 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 parent 
	 * @param parentApply 
	 */
	public ApplyEditorWindow(ApplyType apply, ApplyType parentApply, FunctionArgument argument, Object parent) {
		buildMainLayout();
		//setCompositionRoot(mainLayout);
		setContent(mainLayout);
		//
		// Save
		//
		this.apply = apply;
		this.applyParent = parentApply;
		this.argument = argument;
		this.parent = parent;
		logger.info(this.apply + " " + this.applyParent + " " + this.argument + " " + this.parent);
		//
		// Set our shortcuts
		//
		this.setCloseShortcut(KeyCode.ESCAPE);
		//
		// Initialize
		//
		this.textAreaDescription.setValue(apply.getDescription());
		this.textAreaDescription.setNullRepresentation("");
		this.initializeButton();
		this.initializeTable();
		this.initializeFilters();
		//
		// focus
		//
		this.textFieldFilter.focus();
	}
	
	protected void initializeTable() {
		//
		// Setup GUI properties
		//
		this.tableFunction.setImmediate(true);
		this.tableFunction.setSelectable(true);
		this.tableFunction.setNullSelectionAllowed(false);
		this.tableFunction.setRequired(true);
		this.tableFunction.setRequiredError("You MUST select a function for the Apply");
		//
		// Set its data source
		//
		this.tableFunction.setContainerDataSource(this.container);
		this.tableFunction.setVisibleColumns(new Object[] {"xacmlid", "shortname", "datatypeBean", "isBagReturn"});
		this.tableFunction.setColumnHeaders(new String[] {"Function Xacml ID", "ID", "Return Data Type", "Return Bag?"});
		//
		// Determine appropriate filters
		//
		Datatype datatypeId = null;
		if (this.applyParent == null) {
			if (this.parent instanceof ConditionType) {
				//
				// Only boolean functions allowed
				//
				datatypeId = JPAUtils.findDatatype(XACML3.ID_DATATYPE_BOOLEAN);
			}
		} else {
			String parentFunction = this.applyParent.getFunctionId();
			this.function = JPAUtils.findFunction(parentFunction);
			if (this.function == null) {
				throw new IllegalArgumentException("applyParent's function is not found:" + parentFunction);
			}
			if (this.argument == null) {
				throw new IllegalArgumentException("Need to know what argument apply is ");
			}
			datatypeId = this.argument.getDatatypeBean();
		}
		Map<Datatype, List<FunctionDefinition>> functionMap = JPAUtils.getFunctionDatatypeMap();
		if (datatypeId == null) {
			//
			// All functions are available
			//
			for (Datatype id : functionMap.keySet()) {
				this.addTableEntries(functionMap.get(id));
			}
		} else {
			for (Datatype id : functionMap.keySet()) {
				if (id == null) {
					if (datatypeId == null) {
						this.addTableEntries(functionMap.get(id));
						break;
					}
					continue;
				}
				if (id.getId() == datatypeId.getId()) {
					this.addTableEntries(functionMap.get(id));
					break;
				}
			}
		}
		//
		// Setup double-click
		//
		this.tableFunction.addItemClickListener(new ItemClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void itemClick(ItemClickEvent event) {
				if (event.isDoubleClick()) {
					self.selected();
				}
			}
		});
		//
		// Value change listener
		//
		this.tableFunction.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				logger.info("valueChange " + self.tableFunction.getValue());
				if (self.tableFunction.getValue() != null) {
					self.buttonSelect.setEnabled(true);
				} else {
					self.buttonSelect.setEnabled(false);
				}
			}			
		});
		//
		// Select current value if possible
		//
		if (this.apply != null && this.apply.getFunctionId() != null && this.apply.getFunctionId().isEmpty() == false) {
			FunctionDefinition current = JPAUtils.findFunction(this.apply.getFunctionId());
			if (current != null) {
				this.tableFunction.select(current);
				this.tableFunction.setCurrentPageFirstItemId(current);
			} else {
				logger.warn("Could not find function in table for " + this.apply.getFunctionId());
			}
		} else {
			this.buttonSelect.setEnabled(false);
		}
	}
	
	protected void addTableEntries(List<FunctionDefinition> functions) {
		if (functions == null) {
			logger.warn("NULL list of functions, cannot add to table.");
			return;
		}
		for (FunctionDefinition function : functions) {
			//
			// Just check if this function is available for this
			// apply.
			//
//			if (XACMLFunctionValidator.isFunctionAvailable(function, this.apply, this.argument)) {
				this.container.addBean(function);
//			} else {
//				if (logger.isDebugEnabled()) {
//					logger.debug("Function not available: " + function);
//				}
//			}
		}
	}
	
	protected void initializeButton() {
		this.buttonSelect.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				self.selected();
			}
		});
	}
	
	protected void initializeFilters() {
		this.textFieldFilter.setImmediate(true);
		this.textFieldFilter.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;
			SimpleStringFilter currentFilter = null;
			
			@Override
			public void textChange(TextChangeEvent event) {
				//
				// Remove current filter
				//
				if (this.currentFilter != null) {
					self.container.removeContainerFilter(this.currentFilter);
					this.currentFilter = null;
				}
				//
				// Get the text
				//
				String value = event.getText();
				if (value != null && value.length() > 0) {
					//
					// Add the new filter
					//
					this.currentFilter = new SimpleStringFilter("shortname", value, true, false);
					self.container.addContainerFilter(this.currentFilter);
				}
			}
		});
		
		this.comboBoxDatatypeFilter.setContainerDataSource(((XacmlAdminUI) UI.getCurrent()).getDatatypes());
		this.comboBoxDatatypeFilter.setImmediate(true);
		this.comboBoxDatatypeFilter.setItemCaptionMode(ItemCaptionMode.PROPERTY);
		this.comboBoxDatatypeFilter.setItemCaptionPropertyId("xacmlId");
		this.comboBoxDatatypeFilter.setNullSelectionAllowed(true);
		this.comboBoxDatatypeFilter.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;
			Container.Filter currentFilter = null;

			@Override
			public void valueChange(ValueChangeEvent event) {
				//
				// Remove current filter
				//
				if (this.currentFilter != null) {
					self.container.removeContainerFilter(this.currentFilter);
					this.currentFilter = null;
				}
				//
				// Get the current selection
				//
				Object id = self.comboBoxDatatypeFilter.getValue();
				if (id == null) {
					return;
				}
				//
				// Setup the filter
				//
				final Datatype datatype = ((XacmlAdminUI) UI.getCurrent()).getDatatypes().getItem(id).getEntity();
				this.currentFilter = new Container.Filter() {
					private static final long serialVersionUID = 1L;

					@Override
					public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException {
						if (itemId instanceof FunctionDefinition) {
							Datatype dt = ((FunctionDefinition) itemId).getDatatypeBean();
							if (dt == null) {
								return false;
							}
							return dt.getXacmlId().equals(datatype.getXacmlId());
						}
						return false;
					}
					
					@Override
					public boolean appliesToProperty(Object propertyId) {
						if (propertyId != null && propertyId.toString().equals("datatypeBean")) {
							return true;
						}
						return false;
					}
				};
				self.container.addContainerFilter(this.currentFilter);
			}
		});
		
		this.checkBoxFilterIsBag.setImmediate(true);
		this.checkBoxFilterIsBag.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;
			Filter currentFilter = null;

			@Override
			public void valueChange(ValueChangeEvent event) {
				//
				// Remove current filter
				//
				if (this.currentFilter != null) {
					self.container.removeContainerFilter(this.currentFilter);
					this.currentFilter = null;
				}
				//
				// Is it checked?
				//
				if (self.checkBoxFilterIsBag.getValue() == false) {
					//
					// Nope, get out of here
					//
					return;
				}
				//
				// Add the filter
				//
				this.currentFilter = new Compare.Equal("isBagReturn", true);
				self.container.addContainerFilter(this.currentFilter);
			}
		});
	}
	
	protected	void	selected() {
		//
		// Is there a selected function?
		//
		try {
			//
			// Run the commit
			//
			this.textAreaDescription.commit();
			this.tableFunction.commit();
			//
			// Commit worked, get the selected function
			//
			Object id = this.tableFunction.getValue();
			//
			// Sanity check, it *should* never be null
			// unless someone changed the initialization code.
			//
			if (id == null || ! (id instanceof FunctionDefinition)) {
				throw new InvalidValueException(this.tableFunction.getRequiredError());
			}
			//
			// Get the actual function and save it into the apply
			//
			this.function = (FunctionDefinition) id;
			this.apply.setDescription(this.textAreaDescription.getValue());
			this.apply.setFunctionId(function.getXacmlid());
		} catch (SourceException | InvalidValueException e) {
			//
			// Vaadin GUI will display message
			//
			return;
		}
		/**
		//
		// Make sure the arguments are good
		//
		final ApplyType copyApply = XACMLObjectCopy.copy(this.apply);
		final ApplyArgumentsEditorWindow window = new ApplyArgumentsEditorWindow(copyApply, this.function);
		window.setCaption("Define Arguments for " + this.function.getShortname());
		window.setModal(true);
		window.addCloseListener(new CloseListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void windowClose(CloseEvent e) {
				//
				// Did the user click save?
				//
				if (window.isSaved() == false) {
					return;
				}
				//
				// Save our arguments
				//
				self.apply.getExpression().clear();
				self.apply.getExpression().addAll(copyApply.getExpression());
				//
				// We are saved
				//
				self.isSaved = true;
				//
				// Fire
				//
				self.fireEvent(self.apply, self.applyParent, self.argument, self.parent);
				//
				// Close the apply editor window
				//
				self.close();
			}
		});
		window.center();
		UI.getCurrent().addWindow(window);
		**/
		//
		// We are saved
		//
		self.isSaved = true;
		//
		// Fire
		//
		self.fireEvent(self.apply, self.applyParent, self.argument, self.parent);
		//
		// Close the apply editor window
		//
		self.close();
	}

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

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

	@Override
	public void fireEvent(ApplyType apply, ApplyType parent, FunctionArgument argument, Object container) {
		this.notifier.fireEvent(apply, parent, argument, container);
	}

	public boolean isSaved() {
		return this.isSaved;
	}
	
	public FunctionDefinition	getSelectedFunction() {
		return this.function;
	}
	
	@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");
		
		// horizontalLayout_1
		horizontalLayout_1 = buildHorizontalLayout_1();
		mainLayout.addComponent(horizontalLayout_1);
		
		// tableFunction
		tableFunction = new Table();
		tableFunction.setCaption("Select A Function");
		tableFunction.setImmediate(false);
		tableFunction.setWidth("100.0%");
		tableFunction.setHeight("-1px");
		tableFunction.setInvalidAllowed(false);
		tableFunction.setRequired(true);
		mainLayout.addComponent(tableFunction);
		mainLayout.setExpandRatio(tableFunction, 1.0f);
		
		// buttonSelect
		buttonSelect = new Button();
		buttonSelect.setCaption("Select and Continue");
		buttonSelect.setImmediate(true);
		buttonSelect.setWidth("-1px");
		buttonSelect.setHeight("-1px");
		mainLayout.addComponent(buttonSelect);
		mainLayout.setComponentAlignment(buttonSelect, new Alignment(48));
		
		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);
		
		// textAreaDescription
		textAreaDescription = new TextArea();
		textAreaDescription.setCaption("Enter A Description");
		textAreaDescription.setImmediate(false);
		textAreaDescription.setWidth("50.0%");
		textAreaDescription.setHeight("-1px");
		horizontalLayout_1.addComponent(textAreaDescription);
		
		// textFieldFilter
		textFieldFilter = new TextField();
		textFieldFilter.setCaption("Filter Function By ID");
		textFieldFilter.setImmediate(false);
		textFieldFilter.setWidth("-1px");
		textFieldFilter.setHeight("-1px");
		horizontalLayout_1.addComponent(textFieldFilter);
		horizontalLayout_1.setComponentAlignment(textFieldFilter,
				new Alignment(9));
		
		// comboBoxDatatypeFilter
		comboBoxDatatypeFilter = new ComboBox();
		comboBoxDatatypeFilter.setCaption("Filter By Data Type");
		comboBoxDatatypeFilter.setImmediate(false);
		comboBoxDatatypeFilter.setWidth("-1px");
		comboBoxDatatypeFilter.setHeight("-1px");
		horizontalLayout_1.addComponent(comboBoxDatatypeFilter);
		horizontalLayout_1.setComponentAlignment(comboBoxDatatypeFilter,
				new Alignment(9));
		
		// checkBoxFilterIsBag
		checkBoxFilterIsBag = new CheckBox();
		checkBoxFilterIsBag.setCaption("Is Bag Filter");
		checkBoxFilterIsBag.setImmediate(false);
		checkBoxFilterIsBag.setWidth("-1px");
		checkBoxFilterIsBag.setHeight("-1px");
		horizontalLayout_1.addComponent(checkBoxFilterIsBag);
		horizontalLayout_1.setComponentAlignment(checkBoxFilterIsBag,
				new Alignment(9));
		
		return horizontalLayout_1;
	}

}
