package eu.osci.messagetypes;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.xml.bind.JAXBException;
import javax.xml.transform.stream.StreamSource;

import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.Message;
import com.sun.xml.ws.api.message.Messages;

import eu.osci.ErrorTextTranslation;
import eu.osci.OSCIException;
import eu.osci.messageparts.JaxbContextHolder;
import eu.osci.messageparts.OSCIFragmentCreator;
import eu.osci.ws._2008._05.transport.MsgBoxCloseRequestType;
import eu.osci.ws._2008._05.transport.ObjectFactory;


/**
 * This class represents the OSCIMsgBoxCloseRequest message out of the specification. It will send the correct
 * OSCI SOAP message to finish an OSCI transaction for fetching OSCI messages or status lists.<br>
 * Copyright © 2010 Freie Hansestadt Bremen. <br>
 * Created by bremen online services Entwicklungs- und Betriebsgesellschaft mbH & Co. KG. <br>
 * This library (Starter Kit) can be used by anybody according to the Bremer Lizenz für freie
 * Softwarebibliotheken. The license terms can be viewed at www.osci.de or can be ordered at the
 * OSCI-Leitstelle (Die Senatorin für Finanzen, Freie Hansestadt Bremen, Postfach 10 15 40, 28015 Bremen).
 * 
 * @author R. Lindemann
 */
public class OSCIMsgBoxCloseRequest extends OSCIRequestParent
{

  /** Logger to log the messages. */
  private Logger LOG = Logger.getLogger(OSCIMsgBoxCloseRequest.class.getName());

  /**
   * <b>For internal usage only!</b>
   */
  protected OSCIMsgBoxCloseRequest()
  {
    super();
  }

  /**
   * This constructor is normally used by the client. The previous request will be given as parameter.
   * 
   * @param _parent The previous request.
   */
  public OSCIMsgBoxCloseRequest(OSCIRequestParent _parent)
  {
    super(_parent);
    LOG.fine("Entry constructor with OSCIRequestParent");
    if ((_parent.getFetchIteratorID() == null) || (_parent.getFetchIteratorID().length() == 0))
    {
      throw new IllegalArgumentException(
                                         OSCIMessage.text.getString(ErrorTextTranslation.ILLEGAL_FETCH_ITERATOR.getConstant()));
    }
  }

  /**
   * Internal method for preparing the sent SOAP message. The header elements of the request will be set here.
   * 
   * @throws JAXBException In the case of serialisation errors.
   */
  protected void prepareSendMessage() throws JAXBException
  {
    LOG.fine("Entry prepareSendMessage()");
    ArrayList<Header> headerList = new ArrayList<Header>();
    super.prepareSendMessage(headerList);
    bindingProvider.setOutboundHeaders(headerList);
  }


  /**
   * This method will send the request to the present server. A SOAP message will be sent and the response
   * message with the fetched message will be created.
   * 
   * @param commitIds The previous Ids that will be committed with this close request.
   * @throws JAXBException In the case of serialisation errors.
   * @throws OSCIException In the case of OSCI SOAP faults.
   */
  public void sendRequest(String... commitIds) throws JAXBException, OSCIException
  {
    LOG.fine("Entry sendRequest");
    prepareSendMessage();
    MsgBoxCloseRequestType msgBoxCloseType = new MsgBoxCloseRequestType();
    msgBoxCloseType.setMsgBoxRequestID(getFetchIteratorID());
    if ((commitIds != null) && (commitIds.length > 0))
    {
      int count = 0;
      while ((commitIds != null) && (count < commitIds.length))
      {
        msgBoxCloseType.getLastMsgReceived().add(OSCIFragmentCreator.createAttributedURI(commitIds[count]));
        LOG.info("Message with messageId: " + commitIds[count] + " will be marked as fetched.");
        count++;
      }
    }
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    JaxbContextHolder.getOSCIJaxBContext()
                     .createMarshaller()
                     .marshal(new ObjectFactory().createMsgBoxCloseRequest(msgBoxCloseType), out);
    Message sendSOAPMessage = Messages.createUsingPayload(new StreamSource(
                                                                           new ByteArrayInputStream(
                                                                                                    out.toByteArray())),
                                                          SOAPVersion.SOAP_12);
    sendMessage(sendSOAPMessage);
    interpretWSAHeaders(sendSOAPMessage.getHeaders());
  }

}
