/*
 *
 *          Copyright (c) 2014,2019  AT&T Knowledge Ventures
 *                     SPDX-License-Identifier: MIT
 */
package com.att.research.xacml.admin.view.windows;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;

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

import com.att.research.xacml.admin.jpa.Attribute;
import com.att.research.xacml.admin.jpa.Datatype;
import com.att.research.xacml.admin.util.JPAUtils;
import com.att.research.xacml.admin.view.components.AttributeDictionarySelectorComponent;
import com.att.research.xacml.admin.view.components.AttributeSimpleCreatorComponent;
import com.att.research.xacml.admin.view.components.AttributeStandardSelectorComponent;
import com.att.research.xacml.admin.view.events.AttributeChangedEventListener;
import com.att.research.xacml.admin.view.events.AttributeChangedEventNotifier;
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.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.CheckBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

public class AttributeSelectionWindow extends Window implements AttributeChangedEventListener {

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
	
	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Button buttonSave;
	@AutoGenerated
	private HorizontalLayout horizontalLayoutAttribute;
	@AutoGenerated
	private HorizontalLayout horizontalLayout_1;
	@AutoGenerated
	private VerticalLayout verticalLayout_2;
	@AutoGenerated
	private CheckBox checkBoxMustBePresent;
	@AutoGenerated
	private TextField textFieldIssuer;
	@AutoGenerated
	private OptionGroup optionGroupAttribute;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static Log logger	= LogFactory.getLog(AttributeSelectionWindow.class);
	private final AttributeSelectionWindow self = this;
	private final Datatype datatype;
	private final Attribute defaultAttribute;
	private AttributeChangedEventNotifier currentComponent = null;
	private Attribute attribute = null;
	private boolean isSaved = false;
	
	public static final String	ATTRIBUTE_OPTION_DICTIONARY = "Use Attribute From Dictionary";
	public static final String	ATTRIBUTE_OPTION_STANDARD = "Use A Standard Attribute";
	public static final String	ATTRIBUTE_OPTION_INPUT = "Input A New Attribute";
	public static final String[] ATTRIBUTE_OPTIONS = new String[] {ATTRIBUTE_OPTION_DICTIONARY, ATTRIBUTE_OPTION_STANDARD, ATTRIBUTE_OPTION_INPUT};
	
	/**
	 * 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 datatype 
	 * @param defaultAttribute 
	 */
	public AttributeSelectionWindow(Datatype datatype, Object defaultAttribute) {
		buildMainLayout();
		//setCompositionRoot(mainLayout);
		setContent(mainLayout);
		//
		// Save data
		//
		this.datatype = datatype;
		if (defaultAttribute == null) {
			this.defaultAttribute = null;
		} else {
			//
			// Given a default attribute
			//
			Attribute tempAttribute;
			if (defaultAttribute instanceof AttributeDesignatorType) {
				tempAttribute = JPAUtils.createAttribute((AttributeDesignatorType) defaultAttribute);
			} else if (defaultAttribute instanceof AttributeSelectorType) {
				tempAttribute = JPAUtils.createAttribute((AttributeSelectorType) defaultAttribute);
			} else {
				this.defaultAttribute = null;
				throw new IllegalArgumentException("Selection window only works with designator or selector objects.");
			}
			//
			// See if the attribute exists in our dictionary
			//
			Attribute dictionaryAttribute = JPAUtils.findAttribute(tempAttribute);
			if (dictionaryAttribute != null) {
				this.defaultAttribute = dictionaryAttribute;
			} else {
				this.defaultAttribute = tempAttribute;
			}
		}
		//
		// Close shortcut
		//
		this.setCloseShortcut(KeyCode.ESCAPE);
		//
		// Initialize GUI
		//
		this.initializeOption();
		this.initializeButtons();
		this.initializeAttribute();
		//
		// Setup attribute
		//
		this.resetAttributeOption();
		//
		// Focus
		//
	}
	
	protected void initializeOption() {
		//
		// Setup datasource and GUI properties
		//
		this.optionGroupAttribute.setImmediate(true);
		this.optionGroupAttribute.addItem(ATTRIBUTE_OPTION_DICTIONARY);
		this.optionGroupAttribute.addItem(ATTRIBUTE_OPTION_STANDARD);
		this.optionGroupAttribute.addItem(ATTRIBUTE_OPTION_INPUT);
		//
		// Respond to events
		//
		this.optionGroupAttribute.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				self.resetAttributeOption();
			}
		});
	}
	
	protected void initializeButtons() {
		this.buttonSave.setClickShortcut(KeyCode.ENTER);
		this.buttonSave.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				try {
					//
					// Commit everything??
					//
					self.textFieldIssuer.commit();
					self.checkBoxMustBePresent.commit();
					self.currentComponent.commit();
					//
					// Save to the attribute
					//
					String issuer = self.textFieldIssuer.getValue();
					if (issuer == null || issuer.length() == 0) {
						self.attribute.setIssuer(null);
					} else {
						self.attribute.setIssuer(issuer);
					}
					self.attribute.setMustBePresent(self.checkBoxMustBePresent.getValue());
					//
					// Mark as saved
					//
					self.isSaved = true;
					//
					// Close the window
					//
					self.close();
				} catch (SourceException | InvalidValueException e) {
					
				}
			}
		});
	}
		
	protected void initializeAttribute() {
		//
		// Are we editing something?
		//
		if (this.defaultAttribute == null) {
			//
			// No, this is a new attribute being created
			//
			this.optionGroupAttribute.select(ATTRIBUTE_OPTION_STANDARD);
			return;
		}
		//
		// Yes, is it in our dictionary?
		//
		Attribute attribute = JPAUtils.findAttribute(this.defaultAttribute);
		if (attribute != null) {
			//
			// Yes its in our dictionary
			//
			this.attribute = attribute;
			this.optionGroupAttribute.select(ATTRIBUTE_OPTION_DICTIONARY);
			return;
		}
		//
		// Is it a standard attribute?
		//
		attribute = JPAUtils.isStandardAttribute(this.defaultAttribute);
		if (attribute == null) {
			//
			// No, start editing via custom input attribute
			//
			this.attribute = this.defaultAttribute;
			this.optionGroupAttribute.select(ATTRIBUTE_OPTION_INPUT);
			return;
		}
		//
		// Yes - its a standard attribute
		//
		this.attribute = attribute;
		this.optionGroupAttribute.select(ATTRIBUTE_OPTION_STANDARD);
	}
	
	protected void resetAttributeOption() {
		//
		// Remove GUI components from layout
		//
		this.horizontalLayoutAttribute.removeAllComponents();
		this.currentComponent = null;
		//
		// Grab our currently selected option value
		//
		Object value = self.optionGroupAttribute.getValue();
		//
		// What is it set to?
		//
		if (value.toString().equals(ATTRIBUTE_OPTION_DICTIONARY)) {
			this.currentComponent = new AttributeDictionarySelectorComponent(this.datatype, this.defaultAttribute);
		} else if (value.toString().equals(ATTRIBUTE_OPTION_STANDARD)) {
			this.currentComponent = new AttributeStandardSelectorComponent(this.datatype, this.defaultAttribute);
		} else if (value.toString().equals(ATTRIBUTE_OPTION_INPUT)) {
			this.currentComponent = new AttributeSimpleCreatorComponent(this.datatype, this.defaultAttribute);
		} else {
			logger.error("Unknown option" + value);
			return;
		}
		this.currentComponent.addListener(this);
		this.horizontalLayoutAttribute.addComponent((CustomComponent) this.currentComponent);
		this.currentComponent.fireAttributeChanged(this.currentComponent.getAttribute());
	}
	
	@Override
	public void attributeChanged(Attribute attribute) {
		if (logger.isDebugEnabled()) {
			logger.debug("attributeChanged: " + attribute);
		}
		this.attribute = attribute;
		if (attribute == null) {
			this.buttonSave.setEnabled(false);
		} else {
			this.buttonSave.setEnabled(true);
		}
	}
	
	public boolean isSaved() {
		return this.isSaved;
	}
	
	public Attribute	getAttribute() {
		return this.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");
		
		// horizontalLayout_1
		horizontalLayout_1 = buildHorizontalLayout_1();
		mainLayout.addComponent(horizontalLayout_1);
		
		// horizontalLayoutAttribute
		horizontalLayoutAttribute = new HorizontalLayout();
		horizontalLayoutAttribute.setImmediate(false);
		horizontalLayoutAttribute.setWidth("-1px");
		horizontalLayoutAttribute.setHeight("-1px");
		horizontalLayoutAttribute.setMargin(false);
		mainLayout.addComponent(horizontalLayoutAttribute);
		mainLayout.setExpandRatio(horizontalLayoutAttribute, 1.0f);
		
		// buttonSave
		buttonSave = new Button();
		buttonSave.setCaption("Select");
		buttonSave.setImmediate(true);
		buttonSave.setWidth("-1px");
		buttonSave.setHeight("-1px");
		mainLayout.addComponent(buttonSave);
		mainLayout.setComponentAlignment(buttonSave, 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);
		
		// optionGroupAttribute
		optionGroupAttribute = new OptionGroup();
		optionGroupAttribute.setCaption("Attribute Source");
		optionGroupAttribute.setImmediate(false);
		optionGroupAttribute.setWidth("-1px");
		optionGroupAttribute.setHeight("-1px");
		optionGroupAttribute.setInvalidAllowed(false);
		horizontalLayout_1.addComponent(optionGroupAttribute);
		
		// verticalLayout_2
		verticalLayout_2 = buildVerticalLayout_2();
		horizontalLayout_1.addComponent(verticalLayout_2);
		
		return horizontalLayout_1;
	}

	@AutoGenerated
	private VerticalLayout buildVerticalLayout_2() {
		// common part: create layout
		verticalLayout_2 = new VerticalLayout();
		verticalLayout_2.setImmediate(false);
		verticalLayout_2.setWidth("-1px");
		verticalLayout_2.setHeight("-1px");
		verticalLayout_2.setMargin(true);
		verticalLayout_2.setSpacing(true);
		
		// textFieldIssuer
		textFieldIssuer = new TextField();
		textFieldIssuer.setCaption("Issuer");
		textFieldIssuer.setImmediate(false);
		textFieldIssuer.setWidth("-1px");
		textFieldIssuer.setHeight("-1px");
		verticalLayout_2.addComponent(textFieldIssuer);
		
		// checkBoxMustBePresent
		checkBoxMustBePresent = new CheckBox();
		checkBoxMustBePresent.setCaption("Attribute Must Be Present");
		checkBoxMustBePresent.setImmediate(false);
		checkBoxMustBePresent.setWidth("-1px");
		checkBoxMustBePresent.setHeight("-1px");
		verticalLayout_2.addComponent(checkBoxMustBePresent);
		
		return verticalLayout_2;
	}

}