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

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

import org.apache.openaz.xacml.admin.XacmlAdminAuthorization;
import org.apache.openaz.xacml.admin.XacmlAdminUI;
import org.apache.openaz.xacml.admin.jpa.Obadvice;
import org.apache.openaz.xacml.admin.view.windows.ObadviceEditorWindow;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.provider.CachingLocalEntityProvider;
import com.vaadin.addon.jpacontainer.provider.CachingMutableLocalEntityProvider;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.event.ShortcutAction.KeyCode;
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.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window.CloseEvent;
import com.vaadin.ui.Window.CloseListener;

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

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Table table;
	@AutoGenerated
	private HorizontalLayout horizontalLayoutToolbar;
	@AutoGenerated
	private ComboBox comboBoxFilter;
	@AutoGenerated
	private Button buttonClone;
	@AutoGenerated
	private Button buttonRemove;
	@AutoGenerated
	private Button buttonNew;
	private static final long serialVersionUID = 1L;
	private static final Log logger	= LogFactory.getLog(ObadviceDictionary.class);
	private final ObadviceDictionary self = this;
	
	private static final Object[] visibleColumns = new Object[] { "type", "xacmlId", "description", "fulfillOn", "modifiedBy", "modifiedDate", "createdBy", "createdDate"};
	private static final String[] columnHeaders = new String[] { "Type", "Attribute ID", "Description", "FulFill/Apply", "Modified By", "Modified Date", "Created By", "Created Date"};
	
	private final JPAContainer<Obadvice>	obadvice  = new JPAContainer<Obadvice>(Obadvice.class);

	/**
	 * 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 jpaContainer 
	 */
	public ObadviceDictionary() {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		//
		// Setup container
		//
		boolean isReadOnly;
		if (((XacmlAdminUI)UI.getCurrent()).isAuthorized( 
				XacmlAdminAuthorization.AdminAction.ACTION_WRITE, 
				XacmlAdminAuthorization.AdminResource.RESOURCE_DICTIONARIES)) {
			if (logger.isDebugEnabled()) {
				logger.debug("write access");
			}
			isReadOnly = false;
			this.obadvice.setEntityProvider(new CachingMutableLocalEntityProvider<Obadvice>(Obadvice.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
		} else {
			if (logger.isDebugEnabled()) {
				logger.debug("read only access");
			}
			isReadOnly = true;
			this.obadvice.setEntityProvider(new CachingLocalEntityProvider<Obadvice>(Obadvice.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
		}
		//
		// initialize
		//
		this.initializeTable(isReadOnly);
		this.initializeButtons(isReadOnly);
		this.initializeCombo();
	}
	
	protected void initializeTable(boolean isReadOnly) {
		//
		// Set our container
		//
		this.table.setContainerDataSource(this.obadvice);
		//
		// Initialize GUI properties
		//
		this.table.setVisibleColumns(visibleColumns);
		this.table.setColumnHeaders(columnHeaders);
		this.table.setImmediate(true);
		this.table.setColumnCollapsingAllowed(true);
		//
		// Is read only
		//
		if (isReadOnly) {
			return;
		}
		this.table.setSelectable(true);
		//
		// Respond to selections
		//
		this.table.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.buttonRemove.setEnabled(self.table.getValue() != null);
				self.buttonClone.setEnabled(self.table.getValue() != null);
			}			
		});
	}
	
	protected void initializeButtons(boolean isReadOnly) {
		if (isReadOnly) {
			this.buttonNew.setVisible(false);
			this.buttonRemove.setVisible(false);
			this.buttonClone.setVisible(false);
			return;
		}
		//
		// NEW button
		//
		this.buttonNew.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				//
				// Create window
				//
				String domain = XacmlAdminUI.getDomain();
				String userid = ((XacmlAdminUI)UI.getCurrent()).getUserid();
				final Obadvice oa = new Obadvice(domain, userid);
				final EntityItem<Obadvice> entity = self.obadvice.createEntityItem(oa);
				final ObadviceEditorWindow editor = new ObadviceEditorWindow(entity);
				editor.setCaption("Add New Obligation/Advice");
				editor.setCloseShortcut(KeyCode.ESCAPE);
				editor.setModal(true);
				editor.addCloseListener(new CloseListener() {
					private static final long serialVersionUID = 1L;

					@Override
					public void windowClose(CloseEvent e) {
						if (editor.isSaved()) {
							self.obadvice.addEntity(oa);
							logger.info("Added new obligation/advice: " + oa);
						}
					}
				});
				editor.center();
				UI.getCurrent().addWindow(editor);
			}
		});
		//
		// Disable remove/clone buttons to start
		//
		this.buttonRemove.setEnabled(false);
		this.buttonClone.setEnabled(false);
		//
		// REMOVE button
		//
		this.buttonRemove.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				self.obadvice.removeItem(self.table.getValue());
			}
		});
		//
		// CLONE button
		//
		this.buttonClone.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				// TODO
			}
		});
	}
	
	protected void initializeCombo() {
		//
		// Add filter values
		//
		this.comboBoxFilter.addItem(Obadvice.OBLIGATION);
		this.comboBoxFilter.addItem(Obadvice.ADVICE);
		//
		// Initialize GUI properties
		//
		this.comboBoxFilter.setImmediate(true);
		this.comboBoxFilter.setNullSelectionAllowed(true);
		//
		//
		this.comboBoxFilter.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				//
				// Remove filters
				//
				self.obadvice.removeAllContainerFilters();
				//
				// What was selected?
				//
				Object id = self.comboBoxFilter.getValue();
				if (id != null) {
					//
					// Add filter
					//
					if (id.equals(Obadvice.OBLIGATION)) {
						self.obadvice.addContainerFilter(new Compare.Equal("type", Obadvice.OBLIGATION));
					} else if (id.equals(Obadvice.ADVICE)) {
						self.obadvice.addContainerFilter(new Compare.Equal("type", Obadvice.ADVICE));
					}
				}
			}
		});
	}

	public void refreshContainer() {
		this.obadvice.refresh();
	}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("100%");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(true);
		mainLayout.setSpacing(true);
		
		// top-level component properties
		setWidth("100.0%");
		setHeight("-1px");
		
		// horizontalLayoutToolbar
		horizontalLayoutToolbar = buildHorizontalLayoutToolbar();
		mainLayout.addComponent(horizontalLayoutToolbar);
		
		// table
		table = new Table();
		table.setImmediate(true);
		table.setWidth("-1px");
		table.setHeight("-1px");
		mainLayout.addComponent(table);
		
		return mainLayout;
	}

	@AutoGenerated
	private HorizontalLayout buildHorizontalLayoutToolbar() {
		// common part: create layout
		horizontalLayoutToolbar = new HorizontalLayout();
		horizontalLayoutToolbar.setImmediate(false);
		horizontalLayoutToolbar.setWidth("-1px");
		horizontalLayoutToolbar.setHeight("-1px");
		horizontalLayoutToolbar.setMargin(false);
		horizontalLayoutToolbar.setSpacing(true);
		
		// buttonNew
		buttonNew = new Button();
		buttonNew.setCaption("New");
		buttonNew.setImmediate(true);
		buttonNew
				.setDescription("Add a new advice or obligation to the dictionary.");
		buttonNew.setWidth("-1px");
		buttonNew.setHeight("-1px");
		horizontalLayoutToolbar.addComponent(buttonNew);
		horizontalLayoutToolbar.setComponentAlignment(buttonNew, new Alignment(
				24));
		
		// buttonRemove
		buttonRemove = new Button();
		buttonRemove.setCaption("Remove");
		buttonRemove.setImmediate(true);
		buttonRemove
				.setDescription("Remove the selected advice or obligation from the dictionary.");
		buttonRemove.setWidth("-1px");
		buttonRemove.setHeight("-1px");
		horizontalLayoutToolbar.addComponent(buttonRemove);
		horizontalLayoutToolbar.setComponentAlignment(buttonRemove,
				new Alignment(24));
		
		// buttonClone
		buttonClone = new Button();
		buttonClone.setCaption("Clone");
		buttonClone.setImmediate(true);
		buttonClone.setDescription("Clone the selected obligation/advice.");
		buttonClone.setWidth("-1px");
		buttonClone.setHeight("-1px");
		horizontalLayoutToolbar.addComponent(buttonClone);
		horizontalLayoutToolbar.setComponentAlignment(buttonClone,
				new Alignment(24));
		
		// comboBoxFilter
		comboBoxFilter = new ComboBox();
		comboBoxFilter.setCaption("Filter By Type");
		comboBoxFilter.setImmediate(false);
		comboBoxFilter.setWidth("-1px");
		comboBoxFilter.setHeight("-1px");
		horizontalLayoutToolbar.addComponent(comboBoxFilter);
		
		return horizontalLayoutToolbar;
	}

}
