/*******************************************************************************
 * Copyright (c) 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.bpel.ui.dialogs;


import java.util.Map;

import org.eclipse.bpel.model.util.BPELUtils;
import org.eclipse.bpel.ui.BPELUIPlugin;
import org.eclipse.bpel.ui.Messages;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;



/**
 * A simple dialog that helps the user choose the right namespace prefix
 * for the given namespace.
 *  
 */

@SuppressWarnings("nls")

public class NamespaceMappingDialog extends StatusDialog {
				
	protected static final String NS_PREFIX = "ns" ; 
	
	protected EObject modelObject;
	
	protected Text fTargetNamespace;
	protected Text fPrefixName;    		
		
	protected Map<String,String> fNamespaceMappings;

	private String fTargetNamespaceValue = ""; //$NON-NLS-1$

	protected String fPrefixValue = ""; //$NON-NLS-1$
	
	
	
	private NamespaceMappingDialog (Shell parent) {
		super(parent);
		
		int shellStyle = getShellStyle();		
        setShellStyle(shellStyle | SWT.RESIZE);        
	}
	
	/**
	 * The modelObject is the model element that indicates the scope in which the
	 * variable should be visible.
	 * @param parent the parent shell
	 * @param eObject the model object 
	 */
	
	public NamespaceMappingDialog (Shell parent, EObject eObject) {
		this(parent);
		setStatusLineAboveButtons(true);	
		this.modelObject = eObject;		
		setTitle(Messages.NamespaceMappingDialog_3);
		computeNamespacePrefix();
	}
	
	/**
	 * Set the target namespace for which we want to establish the prefix for.
	 * @param namespace
	 */
	
	public void setNamespace ( String namespace ) {
		
		fTargetNamespaceValue = namespace;
		
		if (fTargetNamespace != null && fTargetNamespaceValue != null ) {
			fTargetNamespace.setText( namespace );
		}				
	}
	
	
	/**
	 * Compute the next available namespace prefix. 
	 */
	
	public void computeNamespacePrefix ( ) {
		
		if (fNamespaceMappings == null) {
			fNamespaceMappings = BPELUtils.getAllNamespacesForContext(modelObject);
		}
		
		String key = NS_PREFIX;
		for(int i=1;; i++) {
			key = NS_PREFIX + i;
			if (fNamespaceMappings.containsKey(key) == false) {
				break;
			}
		}
		
		setPrefix ( key );		
	}
	
	
	
	/**
	 * Set the prefix name.
	 * @param value
	 */
	
	public void setPrefix ( String value ) {
		fPrefixValue = value;
		
		if (fPrefixName != null && fPrefixValue != null) {
			fPrefixName.setText(fPrefixValue);
			validatePrefix();
		}		
	}

	
	
	/**
	 * Get the prefix value
	 * 
	 * @return the prefix value
	 */
	
	public String getPrefix () {
		return fPrefixValue;
	}
	
	
	/**
     * @see Dialog#createDialogArea(Composite)
     */
	
    @Override
	public Control createDialogArea(Composite parent) {
    	    	    	
        Composite contents = (Composite) super.createDialogArea(parent);               
        createNamespaceArea (contents);
        
        return contents;
    }

    
	protected void createNamespaceArea (Composite parent) {
		
		Group group = new Group(parent,SWT.SHADOW_ETCHED_IN);
		group.setText(Messages.NamespaceMappingDialog_4);			
		GridLayout layout = new GridLayout(1,true);
		GridData data = new GridData();        
        data.grabExcessVerticalSpace = false;
        data.grabExcessHorizontalSpace = true;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.BEGINNING;
        
        group.setLayout( layout );
        group.setLayoutData( data );
		
        Composite container = new Composite(group, SWT.NONE);
        
        layout = new GridLayout();
		layout.makeColumnsEqualWidth = true;		
		layout.numColumns = 2;		
		container.setLayout(layout);
		data = new GridData();        
        data.grabExcessVerticalSpace = false;
        data.grabExcessHorizontalSpace = true;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.CENTER;
        container.setLayoutData(data);
        
        		
		// Create Target namespace mappings
        
		Composite namespace  = new Composite(group, SWT.NONE);
		
        layout = new GridLayout();			
		layout.numColumns = 2;		
		namespace.setLayout(layout);
		data = new GridData();        
        data.grabExcessVerticalSpace = true;
        data.grabExcessHorizontalSpace = true;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.FILL;
        namespace.setLayoutData(data);
        
        
        Label label = new Label(namespace,SWT.NONE);
        label.setText(Messages.NamespaceMappingDialog_5);
        
        fTargetNamespace = new Text(namespace,SWT.BORDER);               
        fTargetNamespace.setEditable(false);
        setNamespace( fTargetNamespaceValue );
        
		data = new GridData();        
        data.grabExcessVerticalSpace = false;
        data.grabExcessHorizontalSpace = true;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.FILL;        
        fTargetNamespace.setLayoutData(data);
             
        
        label = new Label(namespace,SWT.NONE);
        label.setText(Messages.NamespaceMappingDialog_6);
        
        fPrefixName = new Text(namespace,SWT.BORDER);        
        setPrefix( fPrefixValue );
        
        fPrefixName.addModifyListener( new ModifyListener () {

			public void modifyText(ModifyEvent e) {
				validatePrefix();
			}
        	
        });
        
		data = new GridData();        
        data.grabExcessVerticalSpace = false;
        data.grabExcessHorizontalSpace = true;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.FILL;        
        fPrefixName.setLayoutData(data);
                        
        // End of target namespace variant.                       
	}

	void validatePrefix ( ) {
		fPrefixValue = fPrefixName.getText();
		
		if (fPrefixValue.length() == 0 || fPrefixValue.startsWith("xml") ) { //$NON-NLS-1$
			// TODO: Prefix validation ?
			updateStatus( new Status(IStatus.ERROR,
					BPELUIPlugin.INSTANCE.getID(),
					0, 
					Messages.NamespaceMappingDialog_8,
					null));		
			return;
		} 
		
		if (fNamespaceMappings.containsKey(fPrefixValue)) {

			updateStatus( new Status(IStatus.ERROR,
					BPELUIPlugin.INSTANCE.getID(),
					0, 
					Messages.NamespaceMappingDialog_9,
					null));					
			return ;
			
		}
		
		for(char ch : fPrefixValue.toCharArray()) {
			if (Character.isWhitespace(ch)) {
				updateStatus( new Status(IStatus.ERROR,
						BPELUIPlugin.INSTANCE.getID(),
						0, 
						Messages.NamespaceMappingDialog_8,
						null));
				return ;
			}
		}
		
		updateStatus(Status.OK_STATUS);					
	}
	
	@Override
	protected void updateStatus (IStatus status) {
		super.updateStatus(status);
	}
	
	
}
