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

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

import com.vaadin.annotations.AutoGenerated;
// import com.vaadin.data.Property.ValueChangeEvent;
// import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.validator.RegexpValidator;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
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.FormLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Window;

public class SubDomainEditorWindow extends Window {

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

	@AutoGenerated
	private FormLayout mainLayout;
	@AutoGenerated
	private Button buttonSave;
	@AutoGenerated
	private TextField textFieldSubdomain;

	//
	// Full domain pattern:
	// "^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$";
	//
	// We just want one part of it.
	//
	private static final String SUBDOMAIN_NAME_PATTERN = "^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$";
	private static final String ERROR_MESSAGE = "Either enter a single subdomain via RFC1123 - letters, digits and a hyphen. Cannot start or end with a hyphen.";
	
	private static final long serialVersionUID = 1L;
	private static final Log logger	= LogFactory.getLog(SubDomainEditorWindow.class);
	private final SubDomainEditorWindow self = this;
	private boolean saved = false;
	private String subdomain = null;
	
	/**
	 * 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 SubDomainEditorWindow(String subdomain) {
		buildMainLayout();
		setContent(mainLayout);
		//
		// Save
		//
		this.subdomain = subdomain;
		//
		// Set our shortcuts
		//
		this.setCloseShortcut(KeyCode.ESCAPE);
		//
		// Initialize
		//
		this.initializeTextField();
		this.initializeButtons();
		//
		// Focus
		//
		this.textFieldSubdomain.focus();
	}
	
	protected void initializeTextField() {
		this.textFieldSubdomain.setRequired(true);
		this.textFieldSubdomain.setRequiredError("Please enter a valid sub domain");
		//
		// Validate the name entered
		//
		this.textFieldSubdomain.addValidator(new RegexpValidator(SUBDOMAIN_NAME_PATTERN, true, ERROR_MESSAGE) {
			private static final long serialVersionUID = 1L;
			
		});
		//
		// Respond to events
		//
		this.textFieldSubdomain.setImmediate(true);
		this.textFieldSubdomain.addTextChangeListener(new TextChangeListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void textChange(TextChangeEvent event) {
				if (event.getText() != null && event.getText().length() > 0) {
					self.buttonSave.setEnabled(true);
				} else {
					self.buttonSave.setEnabled(false);
				}
			}
			
		});
	}
	
	protected void initializeButtons() {
		this.buttonSave.setClickShortcut(KeyCode.ENTER);
		this.buttonSave.setEnabled(false);
		this.buttonSave.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				try {
					//
					// Make sure the text is valid
					//
					self.textFieldSubdomain.validate();
					//
					// Parse our the subdomain parts
					//
					self.subdomain = self.textFieldSubdomain.getValue();
					self.saved = true;
					//
					// Close it up
					//
					self.close();
				} catch (InvalidValueException e) {
					logger.error(e);
				}
			}
			
		});
	}
	
	public boolean isSaved() {
		return this.saved;
	}
	
	public String	getSubDomain() {
		return this.subdomain;
	}

	@AutoGenerated
	private FormLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new FormLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("-1px");
		mainLayout.setHeight("-1px");
		mainLayout.setMargin(true);
		mainLayout.setSpacing(true);
		
		// top-level component properties
		setWidth("-1px");
		setHeight("-1px");
		
		// textFieldSubdomain
		textFieldSubdomain = new TextField();
		textFieldSubdomain.setCaption("Enter Sub Domain");
		textFieldSubdomain.setImmediate(false);
		textFieldSubdomain
				.setDescription("You can enter sub domain name - do not use spaces or wildcard characters.");
		textFieldSubdomain.setWidth("-1px");
		textFieldSubdomain.setHeight("-1px");
		textFieldSubdomain.setInvalidAllowed(false);
		textFieldSubdomain
				.setInputPrompt("Examples: sales hr business marketing.");
		mainLayout.addComponent(textFieldSubdomain);
		mainLayout.setExpandRatio(textFieldSubdomain, 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;
	}

}
