package eu.osci.messagetypes;

import java.io.ByteArrayInputStream;
import java.net.URL;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPFaultException;

import org.w3._2000._09.xmldsig.KeyInfoType;
import org.w3._2000._09.xmldsig.ObjectFactory;
import org.w3._2000._09.xmldsig.X509DataType;
import org.w3._2002._03.xkms.CompoundResultType;
import org.w3._2002._03.xkms.KeyBindingType;
import org.w3._2002._03.xkms.ValidateResultType;
import org.w3._2005._08.addressing.RelatesToType;

import eu.osci._2008._05.common.urn.messagetypes.letterstyle.LetterStyleMessageType;
import eu.osci._2008._05.common.urn.messagetypes.letterstyle.LetterStyleMsgBodyType;
import eu.osci._2008._05.common.urn.messagetypes.letterstyle.LetterStyleMessageType.LetterStyleMsg;
import eu.osci.helper.EndpointLocator;


/**
 * This class is used be many test classes to send and check OSCI messages easily.<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 MessageParent
{

  private static Logger LOG = Logger.getLogger(MessageParent.class.getName());

  public static final String XML_ENC_DATA = "<xenc:EncryptedData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Type=\"http://www.w3.org/2001/04/xmlenc#Content\" Id=\"myID\"><xenc:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes256-cbc\" /><xenc:CipherData><xenc:CipherValue>yGnM4B8IVtwSKwNPwA+b0wNBgP+EUJjhf7N1n4mVK5Y=</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData>";

  // public static final String XML_LETTER_STYLE =
  // "<letter:LetterStyleMessage xmlns:letter=\"http://www.osci.eu/2008/05/common/urn/messageTypes/LetterStyle\"><letter:LetterStyleMsg><letter:LetterStyleMsgBody><letter:Subject>Hier nun das subject</letter:Subject><letter:Text>&lt;my&gt;this is now my xml text&lt;my&gt;</letter:Text></letter:LetterStyleMsgBody></letter:LetterStyleMsg></letter:LetterStyleMessage>";
  public static final String XML_LETTER_STYLE = "<LetterStyleMessage xmlns=\"http://www.osci.eu/2008/05/common/urn/messageTypes/LetterStyle\"></LetterStyleMessage>";

  public static String URL_MSGBOX_HOST = System.getProperty("osci2.server.url",
                                                            "http://localhost:8080/OSCI2Endpoint/");

  public static final String URL_WSDL_USER = URL_MSGBOX_HOST + "user/Alice";

  public static final String URL_WSDL_Synchron = URL_MSGBOX_HOST + "user/Synchron";

  public static final String URL_WSDL_GERNERIC_USER = URL_MSGBOX_HOST + "user/Generic/Alice";

  public static final String WSA_REPLY_TO = URL_MSGBOX_HOST + "user/Bob";

  public final static QName SERVICE = new QName("http://messagebox.osci20.bos-bremen.de", "MsgBoxService");

  public final static QName FETCH_PORT = new QName("http://messagebox.osci20.bos-bremen.de",
                                                   "FetchMsgBoxPort");

  public final static String FIRST_PORT_TO_USE = "LetterStyle";

  public final static String SECOND_PORT_TO_USE = "MyLetterStyle";

  // public final static QName STATUS_LIST = new QName("http://messagebox.osci20.bos-bremen.de",
  // "FetchStatusListPort");
  public static OSCIMessage sendToMsgBox(boolean returnReq) throws Exception
  {
    return sendToMsgBox(null, returnReq);
  }

  public static OSCIMessage sendToMsgBox(RelatesToType relatesTo, boolean returnReq) throws Exception
  {
    return sendToMsgBox(relatesTo, returnReq, 0);
  }

  public static OSCIMessage sendToMsgBox(boolean returnReq, int typeOfBusinessScenario) throws Exception
  {
    return sendToMsgBox(null, returnReq, typeOfBusinessScenario);
  }

  public static OSCIMessage sendToMsgBox(RelatesToType relatesTo,
                                         boolean returnReq,
                                         int typeOfBusinessScenario) throws Exception
  {
    try
    {
      ByteArrayInputStream encData = new ByteArrayInputStream(XML_ENC_DATA.getBytes());
      EndpointLocator endpointLocator = new EndpointLocator(new URL(URL_WSDL_USER));
      LOG.fine("Service: " + endpointLocator.getServiceList().length);
      if (typeOfBusinessScenario == 0)
        endpointLocator.usePort(FIRST_PORT_TO_USE);
      else
        endpointLocator.usePort(SECOND_PORT_TO_USE);
      LOG.fine("Select: " + typeOfBusinessScenario);
      LOG.fine("Port: "
               + endpointLocator.getPortForTypeOfBusinessScenario(endpointLocator.getTypeOfBusinessScenario()));
      OSCIRequest req = new OSCIRequest(endpointLocator);
      req.setFetchedNotificationDemand(URL_WSDL_USER);
      if (relatesTo != null)
        req.addRelatesTo(relatesTo);
      OSCIResponse rsp = req.sendMessage(encData);
      if (returnReq)
        return req;
      else
        return rsp;

    }
    catch (SOAPFaultException ex)
    {
      LOG.log(Level.SEVERE, "Message: " + ex.getFault());
      throw ex;
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      throw ex;
    }
  }

  public static LetterStyleMessageType createLetterStyleMsg()
  {
    LetterStyleMessageType letterStyleJaxbObject = new LetterStyleMessageType();
    LetterStyleMsg msgType = new LetterStyleMsg();
    letterStyleJaxbObject.setLetterStyleMsg(msgType);
    LetterStyleMsgBodyType msgBody = new LetterStyleMsgBodyType();
    letterStyleJaxbObject.getLetterStyleMsg().setLetterStyleMsgBody(msgBody);
    letterStyleJaxbObject.getLetterStyleMsg().getLetterStyleMsgBody().setSubject("Now the subject");
    letterStyleJaxbObject.getLetterStyleMsg()
                         .getLetterStyleMsgBody()
                         .getText()
                         .add("<my>this is now my xml text<my>");

    return letterStyleJaxbObject;
  }

  public CompoundResultType createDummyCompoundResult(ArrayList<X509Certificate> certificates)
    throws CertificateEncodingException
  {
    CompoundResultType compResult = new CompoundResultType();
    for ( X509Certificate certificate : certificates )
    {

      ValidateResultType validate = new ValidateResultType();
      validate.setId("" + new Date().getTime());
      validate.setService("MyResult");
      KeyBindingType keyBinding = new KeyBindingType();
      KeyInfoType keyInfo = new KeyInfoType();

      // X509Data x509Data = new com.sun.xml.security.core.dsig.ObjectFactory().createX509Data();
      X509DataType x509Data = new X509DataType();

      x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName()
              .add(new ObjectFactory().createX509DataTypeX509Certificate(certificate.getEncoded()));
      // x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(certificate);

      keyInfo.getContent().add(new ObjectFactory().createX509Data(x509Data));
      keyBinding.setKeyInfo(keyInfo);
      validate.getKeyBinding().add(keyBinding);
      compResult.getLocateResultOrValidateResultOrRegisterResult().add(validate);
    }
    compResult.setResultMajor("valid");
    compResult.setResultMinor("IO");
    return compResult;
  }

}
