/*
 *  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.jpa.Obadvice;
import org.apache.openaz.xacml.admin.jpa.ObadviceExpression;
import org.apache.openaz.xacml.admin.view.windows.ExpressionEditorWindow;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
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;

public class OaExpressionsEditorComponent extends CustomComponent {

	/*- 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 Button buttonRemove;
	@AutoGenerated
	private Button buttonadd;
	@AutoGenerated
	private Table tableExpressions;
	private static final long serialVersionUID = 1L;
	private final OaExpressionsEditorComponent self = this;
	private final JPAContainer<ObadviceExpression> container;
	private final EntityItem<Obadvice> oa;
	
	/**
	 * 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 OaExpressionsEditorComponent(EntityItem<Obadvice> oa, JPAContainer<ObadviceExpression> container) {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		//
		// Save
		//
		this.container = container;
		this.oa = oa;
		//
		// Filter the container
		//
		this.container.removeAllContainerFilters();
		this.container.addContainerFilter(new Compare.Equal("obadvice", this.oa.getEntity()));
		//
		// Initialize components
		//
		this.initializeTable();
		this.initializeButtons();
	}
	
	private void initializeTable() {
		this.tableExpressions.setContainerDataSource(this.container);
		this.tableExpressions.setVisibleColumns(new Object[] {"type"});
		this.tableExpressions.setColumnHeaders(new String[] {"Expression Type"});
		this.tableExpressions.setPageLength(this.container.size() + 1);
	}
	
	private void initializeButtons() {
		this.buttonadd.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				ObadviceExpression expression = new ObadviceExpression();
				// TODO - EntityItem is not used - does container.createEntityItem even need to be called?
				// final EntityItem<ObadviceExpression> entity = self.container.createEntityItem(expression);
				self.container.createEntityItem(expression); // See TODO

				final ExpressionEditorWindow editor = new ExpressionEditorWindow();
				editor.setCaption("Edit Attribute");
				editor.setCloseShortcut(KeyCode.ESCAPE);
				editor.setModal(true);
				editor.center();
				UI.getCurrent().addWindow(editor);
			}
			
		});
		this.buttonRemove.setEnabled(false);
		this.buttonRemove.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				self.tableExpressions.removeItem(self.tableExpressions.getValue());
			}
			
		});

	}

	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("-1px");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(false);
		
		// top-level component properties
		setWidth("-1px");
		setHeight("-1px");
		
		// tableExpressions
		tableExpressions = new Table();
		tableExpressions.setCaption("Expressions");
		tableExpressions.setImmediate(false);
		tableExpressions
				.setDescription("The list of expressions for the obligation/advice object.");
		tableExpressions.setWidth("-1px");
		tableExpressions.setHeight("-1px");
		mainLayout.addComponent(tableExpressions);
		
		// horizontalLayout_1
		horizontalLayout_1 = buildHorizontalLayout_1();
		mainLayout.addComponent(horizontalLayout_1);
		
		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);
		
		// buttonadd
		buttonadd = new Button();
		buttonadd.setCaption("Add");
		buttonadd.setImmediate(true);
		buttonadd.setWidth("-1px");
		buttonadd.setHeight("-1px");
		horizontalLayout_1.addComponent(buttonadd);
		
		// buttonRemove
		buttonRemove = new Button();
		buttonRemove.setCaption("Remove");
		buttonRemove.setImmediate(true);
		buttonRemove.setDescription("Remove selected expression(s).");
		buttonRemove.setWidth("-1px");
		buttonRemove.setHeight("-1px");
		horizontalLayout_1.addComponent(buttonRemove);
		
		return horizontalLayout_1;
	}

}
