/*
 *
 *          Copyright (c) 2014,2019  AT&T Knowledge Ventures
 *                     SPDX-License-Identifier: MIT
 */
package com.att.research.xacml.admin.view.components;

import java.util.HashSet;
import java.util.Set;

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

import com.att.research.xacml.admin.jpa.PIPConfigParam;
import com.att.research.xacml.admin.jpa.PIPConfiguration;
import com.att.research.xacml.admin.view.events.FormChangedEventListener;
import com.att.research.xacml.admin.view.events.FormChangedEventNotifier;
import com.att.research.xacml.std.pip.engines.csv.HyperCSVEngine;
import com.vaadin.addon.jpacontainer.EntityItem;
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.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

public class HyperCSVPIPConfigurationComponent extends CustomComponent implements FormChangedEventNotifier {

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

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private TextField textFieldDefinition;
	@AutoGenerated
	private TextField textFieldTarget;
	@AutoGenerated
	private TextField textFieldSource;
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static final String CLASSNAME = "com.att.research.xacml.std.pip.engines.csv.HyperCSVEngine";
	
	private final EntityItem<PIPConfiguration> entity;
	private static final Log logger	= LogFactory.getLog(CustomPIPConfigurationComponent.class);
	private final HyperCSVPIPConfigurationComponent self = this;
	private final BasicNotifier notifier = new BasicNotifier();
	
	/**
	 * 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 entityConfig 
	 */
	public HyperCSVPIPConfigurationComponent(EntityItem<PIPConfiguration> entityConfig) {
		buildMainLayout();
		setCompositionRoot(mainLayout);
		//
		// Save
		//
		this.entity = entityConfig;
		//
		// Initialize
		//
		this.initialize();
	}

	protected void initialize() {
		if (logger.isDebugEnabled()) {
			logger.debug("initializing " + this.entity.getEntity().toString());
		}
		//
		// What are our current values?
		//
		Set<PIPConfigParam> unneeded = new HashSet<PIPConfigParam>();
		for (PIPConfigParam param : this.entity.getEntity().getPipconfigParams()) {
			if (param.getParamName().equals(HyperCSVEngine.PROP_SOURCE)) {
				this.textFieldSource.setData(param);
			} else if (param.getParamName().equals(HyperCSVEngine.PROP_TARGET)) {
				this.textFieldTarget.setData(param);
			} else if (param.getParamName().equals(HyperCSVEngine.PROP_DEFINITION)) {
				this.textFieldDefinition.setData(param);
			} else {
				unneeded.add(param);
			}
		}
		if (unneeded.isEmpty() == false) {
			this.entity.getEntity().getPipconfigParams().removeAll(unneeded);
		}
		//
		//
		//
		this.initializeEntity();
		this.initializeText();
	}
	
	protected void initializeEntity() {
		//
		// Initialize the entity
		//
		this.entity.getEntity().setClassname(CLASSNAME);
		this.entity.getEntity().setRequiresResolvers(true);
	}
	
	protected void initializeText() {
		//
		//
		//
		this.textFieldSource.setNullRepresentation("");
		PIPConfigParam param = (PIPConfigParam) this.textFieldSource.getData();
		if (param != null) {
			this.textFieldSource.setValue(param.getParamValue());
		}
		this.textFieldSource.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldSource.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_SOURCE);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldSource.setData(param);
				}
				param.setParamValue(self.textFieldSource.getValue());
				self.fireFormChangedEvent();
			}
		});
		this.textFieldSource.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldSource.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_SOURCE);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldSource.setData(param);
				}
				param.setParamValue(self.textFieldSource.getValue());
				self.fireFormChangedEvent();
			}
		});
		//
		//
		//
		this.textFieldTarget.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldTarget.getData();
		if (param != null) {
			this.textFieldTarget.setValue(param.getParamValue());
		}
		this.textFieldTarget.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldTarget.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_TARGET);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldTarget.setData(param);
				}
				param.setParamValue(self.textFieldTarget.getValue());
				self.fireFormChangedEvent();
			}
		});
		this.textFieldTarget.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldTarget.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_TARGET);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldTarget.setData(param);
				}
				param.setParamValue(self.textFieldTarget.getValue());
				self.fireFormChangedEvent();
			}
		});
		//
		//
		//
		this.textFieldDefinition.setNullRepresentation("");
		param = (PIPConfigParam) this.textFieldDefinition.getData();
		if (param != null) {
			this.textFieldDefinition.setValue(param.getParamValue());
		}
		this.textFieldDefinition.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldDefinition.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_DEFINITION);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldDefinition.setData(param);
				}
				param.setParamValue(self.textFieldDefinition.getValue());
				self.fireFormChangedEvent();
			}
		});
		this.textFieldDefinition.addValueChangeListener(new ValueChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void valueChange(ValueChangeEvent event) {
				PIPConfigParam param = (PIPConfigParam) self.textFieldDefinition.getData();
				if (param == null) {
					param = new PIPConfigParam(HyperCSVEngine.PROP_DEFINITION);
					self.entity.getEntity().addPipconfigParam(param);
					self.textFieldDefinition.setData(param);
				}
				param.setParamValue(self.textFieldDefinition.getValue());
				self.fireFormChangedEvent();
			}
		});
	}
	
	public void validate() throws InvalidValueException {
		if (logger.isDebugEnabled()) {
			logger.debug("validate");
		}
		this.textFieldSource.validate();
		this.textFieldTarget.validate();
		this.textFieldDefinition.validate();
	}
	
	public void commit() throws SourceException, InvalidValueException {
		if (logger.isDebugEnabled()) {
			logger.debug("commit");
		}
		this.textFieldSource.commit();
		this.textFieldTarget.commit();
		this.textFieldDefinition.commit();
	}

	public void discard() throws SourceException {
		if (logger.isDebugEnabled()) {
			logger.debug("discard");
		}
		this.textFieldSource.discard();
		this.textFieldTarget.discard();
		this.textFieldDefinition.discard();
		//??
		this.entity.getEntity().getPipconfigParams().remove(HyperCSVEngine.PROP_SOURCE);
		this.entity.getEntity().getPipconfigParams().remove(HyperCSVEngine.PROP_TARGET);
		this.entity.getEntity().getPipconfigParams().remove(HyperCSVEngine.PROP_DEFINITION);
	}

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

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

	@Override
	public void fireFormChangedEvent() {
		this.notifier.fireFormChangedEvent();
	}
	
	@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");
		
		// textFieldSource
		textFieldSource = new TextField();
		textFieldSource.setCaption("CSV Source File");
		textFieldSource.setImmediate(false);
		textFieldSource.setDescription("Path to CSV file");
		textFieldSource.setWidth("-1px");
		textFieldSource.setHeight("-1px");
		textFieldSource.setInvalidAllowed(false);
		textFieldSource.setRequired(true);
		textFieldSource.setInputPrompt("Eg. /opt/app/data.csv");
		mainLayout.addComponent(textFieldSource);
		
		// textFieldTarget
		textFieldTarget = new TextField();
		textFieldTarget.setCaption("Table");
		textFieldTarget.setImmediate(false);
		textFieldTarget.setDescription("Name of database table to be created.");
		textFieldTarget.setWidth("-1px");
		textFieldTarget.setHeight("-1px");
		textFieldTarget.setInvalidAllowed(false);
		textFieldTarget.setRequired(true);
		mainLayout.addComponent(textFieldTarget);
		
		// textFieldDefinition
		textFieldDefinition = new TextField();
		textFieldDefinition.setCaption("Table Definition");
		textFieldDefinition.setImmediate(false);
		textFieldDefinition.setDescription("SQL Table Definition");
		textFieldDefinition.setWidth("-1px");
		textFieldDefinition.setHeight("-1px");
		textFieldDefinition.setInvalidAllowed(false);
		textFieldDefinition.setRequired(true);
		mainLayout.addComponent(textFieldDefinition);
		
		return mainLayout;
	}

}
