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

import com.att.research.xacml.admin.XacmlAdminUI;
import com.att.research.xacml.admin.jpa.PolicyAlgorithms;
import com.att.research.xacml.admin.util.JPAUtils;
import com.att.research.xacml.api.XACML3;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.data.Buffered.SourceException;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.validator.RegexpValidator;
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.Label;
import com.vaadin.ui.ListSelect;
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 PolicySetEditorWindow extends Window {

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

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private Button buttonSave;
	@AutoGenerated
	private TextArea textAreaDescription;
	@AutoGenerated
	private ListSelect listSelectAlgorithm;
	@AutoGenerated
	private TextField textFieldVersion;
	@AutoGenerated
	private Label labelID;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private final PolicySetEditorWindow self = this;
	private final PolicySetType policySet;
	private JPAContainer<PolicyAlgorithms> algorithms = ((XacmlAdminUI)UI.getCurrent()).getPolicyAlgorithms();
	private boolean isSaved = false;
	/**
	 * 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 policySet 
	 */
	public PolicySetEditorWindow(PolicySetType policySet) {
		buildMainLayout();
		//setCompositionRoot(mainLayout);
		setContent(mainLayout);
		//
		// Save
		//
		this.policySet = policySet;
		//
		// Close shortcut
		//
		this.setCloseShortcut(KeyCode.ESCAPE);
		//
		// Initialize GUI
		//
		this.initializeLabel();
		this.initializeText();
		this.initializeSelect();
		this.initializeButton();
		//
		// Focus
		//
		this.textAreaDescription.focus();
	}
	
	protected void initializeLabel() {
		if (this.policySet.getPolicySetId() == null) {
			this.policySet.setPolicySetId(((XacmlAdminUI)UI.getCurrent()).newPolicyID());
		}
		this.labelID.setValue(this.policySet.getPolicySetId());
	}
	
	protected void initializeText() {
		//
		//
		//
		this.textAreaDescription.setNullRepresentation("");
		this.textAreaDescription.setValue(this.policySet.getDescription());
		//
		//
		//
		if (this.policySet.getVersion() == null) {
			this.policySet.setVersion("1");
		}
		this.textFieldVersion.setRequiredError("The exact format is: ((\\d+|\\*)\\.)*(\\d+|\\*|\\+)");
		this.textFieldVersion.addValidator(new RegexpValidator("((\\d+|\\*)\\.)*(\\d+|\\*|\\+)", true, "The version MUST a number optionally separated by '.' eg. 1 or 1.0 or 1.1.1 etc."));
		this.textFieldVersion.setValue(this.policySet.getVersion());
	}
	
	protected void initializeSelect() {
		this.listSelectAlgorithm.setContainerDataSource(this.algorithms);
		this.listSelectAlgorithm.setItemCaptionMode(ItemCaptionMode.PROPERTY);
		this.listSelectAlgorithm.setItemCaptionPropertyId("xacmlId");
		this.listSelectAlgorithm.setNullSelectionAllowed(false);
		
		if (this.policySet.getPolicyCombiningAlgId() == null) {
			this.policySet.setPolicyCombiningAlgId(XACML3.ID_POLICY_FIRST_APPLICABLE.stringValue());
		}
		this.listSelectAlgorithm.setValue(JPAUtils.findPolicyAlgorithm(this.policySet.getPolicyCombiningAlgId()).getId());
	}
	
	protected void initializeButton() {
		this.buttonSave.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				try {
					//
					// Commit
					//
					self.listSelectAlgorithm.commit();
					self.textFieldVersion.commit();
					self.textAreaDescription.commit();
					//
					// Save everything
					//
					self.policySet.setDescription(self.textAreaDescription.getValue());
					self.policySet.setVersion(self.textFieldVersion.getValue());
					Object id = self.listSelectAlgorithm.getValue();
					self.policySet.setPolicyCombiningAlgId(algorithms.getItem(id).getEntity().getXacmlId());
					//
					// Mark ourselves as saved
					//
					self.isSaved = true;
					//
					// Close window
					//
					self.close();
				} catch (SourceException | InvalidValueException e) {
					//
					// VAADIN will show the required error message to the user
					//
				}
			}
		});
	}
	
	public boolean isSaved() {
		return this.isSaved;
	}
	
	public PolicySetType getPolicySet() {
		return this.policySet;
	}

	@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");
		
		// labelID
		labelID = new Label();
		labelID.setCaption("Policy Set ID");
		labelID.setImmediate(false);
		labelID.setWidth("100.0%");
		labelID.setHeight("-1px");
		labelID.setValue("Label");
		mainLayout.addComponent(labelID);
		
		// textFieldVersion
		textFieldVersion = new TextField();
		textFieldVersion.setCaption("Version");
		textFieldVersion.setImmediate(false);
		textFieldVersion
				.setDescription("The format is numbers only separated by decimal point.");
		textFieldVersion.setWidth("-1px");
		textFieldVersion.setHeight("-1px");
		textFieldVersion.setInvalidAllowed(false);
		textFieldVersion.setRequired(true);
		textFieldVersion.setInputPrompt("Eg. 1 or 1.0 or 1.0.0 etc.");
		mainLayout.addComponent(textFieldVersion);
		
		// listSelectAlgorithm
		listSelectAlgorithm = new ListSelect();
		listSelectAlgorithm.setCaption("Policy Combining Algorithm");
		listSelectAlgorithm.setImmediate(false);
		listSelectAlgorithm.setWidth("100.0%");
		listSelectAlgorithm.setHeight("-1px");
		listSelectAlgorithm.setInvalidAllowed(false);
		listSelectAlgorithm.setRequired(true);
		mainLayout.addComponent(listSelectAlgorithm);
		
		// textAreaDescription
		textAreaDescription = new TextArea();
		textAreaDescription.setCaption("Description");
		textAreaDescription.setImmediate(false);
		textAreaDescription.setWidth("100.0%");
		textAreaDescription.setHeight("-1px");
		mainLayout.addComponent(textAreaDescription);
		mainLayout.setExpandRatio(textAreaDescription, 1.0f);
		
		// buttonSave
		buttonSave = new Button();
		buttonSave.setCaption("Save");
		buttonSave.setImmediate(true);
		buttonSave.setWidth("-1px");
		buttonSave.setHeight("-1px");
		mainLayout.addComponent(buttonSave);
		mainLayout.setComponentAlignment(buttonSave, new Alignment(48));
		
		return mainLayout;
	}

}