package org.eclipse.wst.wsdl.binding.soap.internal.generator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.wst.wsdl.Binding;
import org.eclipse.wst.wsdl.BindingFault;
import org.eclipse.wst.wsdl.BindingInput;
import org.eclipse.wst.wsdl.BindingOperation;
import org.eclipse.wst.wsdl.BindingOutput;
import org.eclipse.wst.wsdl.ExtensibilityElement;
import org.eclipse.wst.wsdl.Fault;
import org.eclipse.wst.wsdl.Input;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Output;
import org.eclipse.wst.wsdl.Port;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.binding.soap.SOAPAddress;
import org.eclipse.wst.wsdl.binding.soap.SOAPBinding;
import org.eclipse.wst.wsdl.binding.soap.SOAPBody;
import org.eclipse.wst.wsdl.binding.soap.SOAPFactory;
import org.eclipse.wst.wsdl.binding.soap.SOAPFault;
import org.eclipse.wst.wsdl.binding.soap.SOAPOperation;
import org.eclipse.wst.wsdl.internal.generator.ContentGenerator;
import org.w3c.dom.Element;

public class SOAPContentGenerator implements ContentGenerator
{	
	public static final int OPTION_NOT_SET = -1;
	
	public static final int STYLE_DOCUMENT = 1;
	public static final int STYLE_RPC = 2;
	
	public static final int USE_LITERAL = 1;
	public static final int USE_ENCODED = 2;
	
	private int styleOption = OPTION_NOT_SET;
	private int useOption = OPTION_NOT_SET;

  protected String namespaceValue = "";
  protected String addressLocation = ContentGenerator.ADDRESS_LOCATION;

  protected final static String[] requiredNamespaces = {"http://schemas.xmlsoap.org/wsdl/soap/"};
  protected final static String[] preferredNamespacePrefixes = {"soap"};
  
     
  public String[] getRequiredNamespaces()
  {
    return requiredNamespaces;
  }
  
  public String getPreferredNamespacePrefix(String namespace)
  {
	  if (namespace.equals("http://schemas.xmlsoap.org/wsdl/soap/")) {
		  return "soap";
	  }
	  
	  return "";
  }
  
  public void setStyle(int style) {
	  styleOption = style;
  }
  
  public void setUse(int use) {
	  useOption = use;
  }
  
  public void setAddressLocation(String addressLocation) {
	  this.addressLocation = addressLocation;
  }

  public void generatePortContent(Port port)
  {
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(port.getEExtensibilityElements());	  
	  removeExtensebilityElements(port.getEExtensibilityElements(), removeList);

	  SOAPAddress soapAddress= SOAPFactory.eINSTANCE.createSOAPAddress();
	  soapAddress.setLocationURI(addressLocation);
	  port.addExtensibilityElement(soapAddress);
  }  

  public void generateBindingContent(Binding binding, PortType portType)
  {	  
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(binding.getEExtensibilityElements());	  
	  removeExtensebilityElements(binding.getEExtensibilityElements(), removeList);
	
	SOAPFactory soapFactory = SOAPFactory.eINSTANCE;
	SOAPBinding soapBinding = soapFactory.createSOAPBinding();
	soapBinding.setStyle((getStyleOption(binding) == STYLE_DOCUMENT) ? "document" : "rpc");
	soapBinding.setTransportURI("http://schemas.xmlsoap.org/soap/http");
	
	binding.addExtensibilityElement(soapBinding);	
  }

  public void generateBindingOperationContent(BindingOperation bindingOperation, Operation operation)
  {
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(bindingOperation.getEExtensibilityElements());
	  Element bindingOperationElement = bindingOperation.getElement();	
	removeExtensebilityElements(bindingOperation.getEExtensibilityElements(), removeList);
	
	SOAPOperation soapOperation = SOAPFactory.eINSTANCE.createSOAPOperation();
	
	
    String soapActionValue = getNamespace(bindingOperation);
    if (!soapActionValue.endsWith("/"))
    {                
      soapActionValue += "/";
    }                        
    soapActionValue += operation.getName();
	
	soapOperation.setSoapActionURI(soapActionValue);
	
	bindingOperation.addExtensibilityElement(soapOperation);	
  }  

  public void generateBindingInputContent(BindingInput bindingInput, Input input)
  {
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(bindingInput.getEExtensibilityElements());
	  Element bindingInputElement = bindingInput.getElement();
	removeExtensebilityElements(bindingInput.getEExtensibilityElements(), removeList);
	
	SOAPFactory soapFactory = SOAPFactory.eINSTANCE;
	SOAPBody soapBody = soapFactory.createSOAPBody();
	soapBody.setUse((getUseOption(null) == USE_ENCODED) ? "encoded" : "literal");
	if (getUseOption(bindingInput) == USE_ENCODED && getStyleOption(bindingInput) == STYLE_RPC)
    {
		List encodingList = new BasicEList();
		encodingList.add("http://schemas.xmlsoap.org/soap/encoding/");
		soapBody.setEncodingStyles(encodingList);
	  	soapBody.setNamespaceURI(getNamespace(bindingInput));
    }
    else if (getUseOption(bindingInput) == USE_LITERAL && getStyleOption(bindingInput) == STYLE_RPC) {
	  	soapBody.setNamespaceURI(getNamespace(bindingInput));
    }
	
	bindingInput.addExtensibilityElement(soapBody);
  }

  public void generateBindingOutputContent(BindingOutput bindingOutput, Output output)
  {
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(bindingOutput.getEExtensibilityElements());
	  Element bindingOutputElement = bindingOutput.getElement();
	removeExtensebilityElements(bindingOutput.getEExtensibilityElements(), removeList);
	
	SOAPFactory soapFactory = SOAPFactory.eINSTANCE;
	SOAPBody soapBody = soapFactory.createSOAPBody();
	soapBody.setUse((getUseOption(bindingOutput) == USE_ENCODED) ? "encoded" : "literal");
	if (getUseOption(bindingOutput) == USE_ENCODED && getStyleOption(bindingOutput) == STYLE_RPC)
    {
		List encodingList = new BasicEList();
		encodingList.add("http://schemas.xmlsoap.org/soap/encoding/");
		soapBody.setEncodingStyles(encodingList);
	  	soapBody.setNamespaceURI(getNamespace(bindingOutput));
    }
    else if (getUseOption(bindingOutput) == USE_LITERAL && getStyleOption(bindingOutput) == STYLE_RPC) {
	  	soapBody.setNamespaceURI(getNamespace(bindingOutput));
    }
	
	bindingOutput.addExtensibilityElement(soapBody);	
  }         

  public void generateBindingFaultContent(BindingFault bindingFault, Fault fault)
  {                            
	  // We blow away any existing ExtensibilityElements/content before we generate it
	  // Is it worth being smarter?  Look for matching content first and create those which aren't found????
	  List removeList = new ArrayList(bindingFault.getEExtensibilityElements());
	  Element bindingFaultElement = bindingFault.getElement();
	removeExtensebilityElements(bindingFault.getEExtensibilityElements(), removeList);
	
	SOAPFactory soapFactory = SOAPFactory.eINSTANCE;
	SOAPFault soapFault = soapFactory.createSOAPFault();
	soapFault.setUse((getUseOption(bindingFault) == USE_ENCODED) ? "encoded" : "literal");
	soapFault.setName(fault.getName());
	soapFault.setNamespaceURI(getNamespace(bindingFault));

	if (getUseOption(bindingFault) == USE_ENCODED && getStyleOption(bindingFault) == STYLE_RPC)
    {
		List encodingList = new BasicEList();
		encodingList.add("http://schemas.xmlsoap.org/soap/encoding/");
		soapFault.setEncodingStyles(encodingList);
    }
	
	bindingFault.addExtensibilityElement(soapFault);
  }
  
  private String getNamespace(WSDLElement wsdlElement) {
	  if (namespaceValue.equals("") && wsdlElement != null) {
		  namespaceValue = wsdlElement.getEnclosingDefinition().getTargetNamespace();
	  }
	  
	  return namespaceValue;
  }
  
  private void removeExtensebilityElements(List originalList, List removeList) {
	  Iterator removeIt = removeList.iterator();
	  while (removeIt.hasNext()) {
		  originalList.remove(removeIt.next());
	  }
  }
  
  private Binding getBindingObject(Object genericBindingObject) {
	  Object parent = genericBindingObject;
	  
	  int index = 0;
	  while (parent != null && index < 5) {
		  parent = getGenericBindingObjectParent(parent);
		  if (parent instanceof Binding) {
			  break;
		  }
		  index++;
	  }

	  return (parent instanceof Binding)? (Binding) parent : null;
  }
  
  private Object getGenericBindingObjectParent(Object genericBindingObject) {
	  Object parent = null;
	  
	  if (genericBindingObject != null) {
		  if (genericBindingObject instanceof BindingOperation) {
			  parent = ((BindingOperation) genericBindingObject).getContainer();
		  }
		  else if (genericBindingObject instanceof BindingInput) {
			  parent = ((BindingInput) genericBindingObject).getContainer();
		  }
		  else if (genericBindingObject instanceof BindingOutput) {
			  parent = ((BindingOutput) genericBindingObject).getContainer();
		  }
		  else if (genericBindingObject instanceof BindingFault) {
			  parent = ((BindingFault) genericBindingObject).getContainer();
		  }	  
	  }
	  
	  return parent;	  
  }
  
    private int getStyleOption(Object genericBindingObject) {
	  if (styleOption == OPTION_NOT_SET && genericBindingObject != null) {
		  // init() was never called, try to determine the 'style' based on what we have/know
		  Binding binding = getBindingObject(genericBindingObject);
		  
		  // Try to determine the style from the Binding Object
		  if (binding != null) {
			  List list = binding.getEExtensibilityElements();
			  Iterator valuesIt = getExtensibilityElementAttributeValue(list, "style").iterator();

			  while (valuesIt.hasNext()) {
				  String style = (String) valuesIt.next();
				  
				  if (style.equals("document")) {
					  styleOption = STYLE_DOCUMENT;
				  }
				  else if (style.equals("rpc")) {
					  styleOption = STYLE_RPC;  
				  }
				  
				  if (styleOption != OPTION_NOT_SET) {
					  break;
				  }
			  }
		  }
	  }
	  
	  if (styleOption == OPTION_NOT_SET) {
		  styleOption = STYLE_DOCUMENT;
	  }
	  
	  return styleOption;
  }
	
	  private int getUseOption(Object genericBindingObject) {
		  if (useOption == OPTION_NOT_SET) {
			  // init() was never called, try to determine the 'use' based on what we have/know
			  Iterator messageRefIt = getMessageReferenceBindingObjects(genericBindingObject).iterator();
			  
			  // Try to determine the use from the list of BindingInputs, BindingOutputs, and BindingFaults
			  while (messageRefIt.hasNext()) {
				  Object messageRef = messageRefIt.next();
				  List values = new ArrayList();
				  
				  if (messageRef instanceof BindingInput) {
					  List list = ((BindingInput) messageRef).getEExtensibilityElements();
					  values = getExtensibilityElementAttributeValue(list, "use");
				  }
				  else if (messageRef instanceof BindingOutput) {
					  List list = ((BindingOutput) messageRef).getEExtensibilityElements();
					  values = getExtensibilityElementAttributeValue(list, "use");
				  }
				  else if (messageRef instanceof BindingFault) {
					  List list = ((BindingFault) messageRef).getEExtensibilityElements();
					  values = getExtensibilityElementAttributeValue(list, "use");				  
				  }

				  Iterator valuesIt = values.iterator();
				  while (valuesIt.hasNext()) {
					  String use = (String) valuesIt.next();
					  
					  if (use.equals("literal")) {
						  useOption = USE_LITERAL;
					  }
					  else if (use.equals("encoded")) {
						  useOption = USE_ENCODED;  
					  }
				  }
				  
				  if (useOption != OPTION_NOT_SET) {
					  break;
				  }
			  }
		  }

		  if (useOption == OPTION_NOT_SET) {
			  useOption = USE_LITERAL;
		  }
		  
		  return useOption;
	  }
	  
	  private List getMessageReferenceBindingObjects(Object genericBindingObject) {
		  List list = new ArrayList();
		  Binding binding = getBindingObject(genericBindingObject);
		  
		  if (binding != null) {
			  Iterator operationsIt = binding.getEBindingOperations().iterator();
		  
			  while (operationsIt.hasNext()) {
				  BindingOperation op = (BindingOperation) operationsIt.next();
				  list.add(op.getEBindingInput());
				  list.add(op.getEBindingOutput());
				  list.addAll(op.getEBindingFaults());
			  }	  
		  }
		  
		  return list;
	  }
	
	  private List getExtensibilityElementAttributeValue(List eeList, String attributeKey) {
		  List values = new ArrayList();
		  Iterator eeElementsIt = eeList.iterator();
		  
		  while (eeElementsIt.hasNext()) {
			  ExtensibilityElement eeElement = (ExtensibilityElement) eeElementsIt.next();
			  String attributeValue = eeElement.getElement().getAttribute(attributeKey);
			  if (attributeValue != null && !attributeValue.equals("")) {
				  values.add(attributeValue);
			  }		  
		  }
		  
		  return values;
	  }
	  
	  public String getProtocol() {
		  return "SOAP";
	  }
} 