package at.gv.egovernment.moa.spss.api.xmlbind;

import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import at.gv.egovernment.moa.util.Constants;

import at.gv.egovernment.moa.spss.MOASystemException;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateXMLSignatureResponse;
import at.gv.egovernment.moa.spss.api.xmlsign.CreateXMLSignatureResponseElement;
import at.gv.egovernment.moa.spss.api.xmlsign.ErrorResponse;
import at.gv.egovernment.moa.spss.api.xmlsign.SignatureEnvironmentResponse;

/**
 * Convert a <code>CreateXMLSignatureResponse</code> API object into its
 * XML representation, according to the MOA XML schema.
 * 
 * @author Patrick Peck
 * @version $Id$
 */
public class CreateXMLSignatureResponseBuilder {
  private static final String MOA_NS_URI = Constants.MOA_NS_URI;

  /** The XML document containing the response element. */
  private Document responseDoc;
  /** The response <code>CreateXMLSignatureResponse</code> DOM element. */
  private Element responseElem;

  /**
   * Create a new <code>CreateXMLSignatureResponseBuilder</code>:
   * 
   * @throws MOASystemException An error occurred setting up the resulting
   * XML document.
   */
  public CreateXMLSignatureResponseBuilder() throws MOASystemException {
    responseDoc =
      ResponseBuilderUtils.createResponse("CreateXMLSignatureResponse");
    responseElem = responseDoc.getDocumentElement();
  }

  /**
   * Build a document containing a <code>CreateXMLSignatureResponse</code>
   * DOM element being the XML representation of the given 
   * <code>CreateXMLSignatureResponse</code> API object.
   * 
   * @param response The <code>CreateXMLSignatureResponse</code> to convert
   * to XML.
   * @return A document containing the <code>CreateXMLSignatureResponse</code>
   * DOM element.
   */
  public Document build(CreateXMLSignatureResponse response) {
    Iterator iter;

    for (iter = response.getResponseElements().iterator(); iter.hasNext();) {
      CreateXMLSignatureResponseElement responseElement =
        (CreateXMLSignatureResponseElement) iter.next();

      switch (responseElement.getResponseType()) {
        case CreateXMLSignatureResponseElement.SIGNATURE_ENVIRONMENT_RESPONSE :
          SignatureEnvironmentResponse envResponse =
            (SignatureEnvironmentResponse) responseElement;
          addSignatureEnvironment(envResponse);
          break;

        case CreateXMLSignatureResponseElement.ERROR_RESPONSE :
          ErrorResponse errorResponse = (ErrorResponse) responseElement;
          addErrorResponse(errorResponse);
          break;
      }

    }

    return responseDoc;
  }

  /**
   * Add a <code>SignatureEnvironment</code> element to the response.
   * 
   * @param envResponse The content to put under the
   * <code>SignatureEnvironment</code> element. This should either be a
   * <code>dsig:Signature</code> element (in case of a detached signature) or
   * the signature environment containing the signature (in case of
   * an enveloping signature).
   */
  private void addSignatureEnvironment(SignatureEnvironmentResponse envResponse) {
    Element content = envResponse.getSignatureEnvironment();
    Node importedSignature = responseDoc.importNode(content, true);
    Element signatureEnvironment =
      responseDoc.createElementNS(MOA_NS_URI, "SignatureEnvironment");
    signatureEnvironment.appendChild(importedSignature);
    responseElem.appendChild(signatureEnvironment);
  }

  /**
   * Add a <code>ErrorResponse</code> element to the response.
   *  
   * @param errorResponse The API object containing the information to put into
   * the <code>ErrorResponse</code> DOM element.
   */
  private void addErrorResponse(ErrorResponse errorResponse) {
    Element errorElem =
      responseDoc.createElementNS(MOA_NS_URI, "ErrorResponse");
    Element errorCodeElem =
      responseDoc.createElementNS(MOA_NS_URI, "ErrorCode");
    Element infoElem = responseDoc.createElementNS(MOA_NS_URI, "Info");
    String errorCodeStr = Integer.toString(errorResponse.getErrorCode());

    errorCodeElem.appendChild(responseDoc.createTextNode(errorCodeStr));
    errorElem.appendChild(errorCodeElem);
    infoElem.appendChild(responseDoc.createTextNode(errorResponse.getInfo()));
    errorElem.appendChild(errorCodeElem);
    errorElem.appendChild(infoElem);
    responseElem.appendChild(errorElem);
  }

}