package de.tu_dresden.diplom.richter_mirko_mat2628335.witness.handler;

import de.tu_dresden.diplom.richter_mirko_mat2628335.common.NS;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.Constants;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.CoordinationContext;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.crypto.SignUtil;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.handler.BaseHandler;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.keystore.ApplicationSpecificKeystoreUtility;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.Witness;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.utils.XMLUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;

/**
 * 
 */
public class CountingContextGenerator extends BaseHandler {

   private static final Logger logger = Logger.getLogger(CountingContextGenerator.class);

   public void invoke(MessageContext messageContext) throws AxisFault {
      String fn = "[invoke]";
      String logInfo = (String) getOption("logInfo");
      if(logInfo != null){
         //fn = fn + " -> " + logInfo + "::";
         MDC.put("logInfo", logInfo);
      }
      if (logger.isDebugEnabled()) logger.debug(fn + " --> COUNTINGCONTEXTGENERATOR");
      CoordinationContext ctxCreationResp = getHeaderContextCreationResponse(messageContext);
      if (ctxCreationResp == null) {
         logger.error(fn + " Couldn't find ContextCreationResponse");
      } else {
         try {
            addCoordinationContextIntoHeader(messageContext, ctxCreationResp);
         } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
         }
      }
      if (logger.isDebugEnabled()) logger.debug(fn + " <-- COUNTINGCONTEXTGENERATOR");
      MDC.remove("logInfo");
   }

   private CoordinationContext getHeaderContextCreationResponse(MessageContext msgCtx) {
      return (CoordinationContext) msgCtx.getProperty(Witness.PROP_MESSAGECONTEXT_CONTEXTCREATIONRESPONSE);
   }

   private void addCoordinationContextIntoHeader(MessageContext ctx, CoordinationContext response) throws Exception {
      final String fn = "[addCoordinationContextIntoHeader2]";
      Message msg = ctx.getCurrentMessage();
      SOAPEnvelope soapEnvelope = msg.getSOAPEnvelope();
      createCountingContextInSOAPHeader(soapEnvelope);
      Document doc = soapEnvelope.getAsDocument();
      Element envelope = doc.getDocumentElement();
      if (logger.isDebugEnabled()) logger.debug(fn + " looking for '" + Constants.ELEMENT_NAME_COUNTING_CONTEXT + "'-Elements within namespace '" + NS.ACCESS_CONTROL_PROTOTYP_NAMESPACE + "' ...");
      NodeList countingContexts = envelope.getElementsByTagNameNS(NS.ACCESS_CONTROL_PROTOTYP_NAMESPACE, Constants.ELEMENT_NAME_COUNTING_CONTEXT);
      if (logger.isDebugEnabled()) logger.debug(fn + " ... found '" + countingContexts.getLength() + "' elements");
      Element countingContext = (Element) countingContexts.item(0);

      Element context = response.makeContextElement(doc, countingContext);
      countingContext.appendChild(context);

      //SignUtil.signEnvelopedXSS4J(doc, context, ApplicationSpecificKeystoreUtility.ENTITY_WITNESS);
      //SignUtil.signEnvelopedVerisign(doc, context, ApplicationSpecificKeystoreUtility.ENTITY_WITNESS);
      String documentString = XMLUtils.DocumentToString(doc);
      StreamSource source = new StreamSource(new StringReader(documentString));
      msg.getSOAPPart().setContent(source);

   }


}
