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

import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.axis.MessageContext;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.utils.XMLUtils;
import org.apache.axis.message.SOAPEnvelope;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.handler.data.IFHandlingInfo;
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.IFCountingContext;

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

/**
 * 
 */
public class CountingContextWriter extends BaseHandler {

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

   /**
    * @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
    */
   public void invoke(MessageContext messageContext) throws AxisFault {
      String fn = "[invoke]";
      String logInfo = (String) getOption(OPTION_LOG_INFO);
      if (logInfo != null) {
         //fn = fn + " -> " + logInfo + "::";
         MDC.put(OPTION_LOG_INFO, logInfo);
      }
      if (logger.isDebugEnabled()) logger.debug(fn + " --> COUNTINGCONTEXTWRITER");
      IFHandlingInfo handlingInfo = getHandlingInfo();
      if (handlingInfo.isSuccess()) {
         try {
            if (logger.isDebugEnabled()) logger.debug(fn + " starting to embedd the given coordinationContext into the header");
            Message msg = messageContext.getCurrentMessage();
            SOAPEnvelope soapEnvelope = msg.getSOAPEnvelope();
            createCountingContextInSOAPHeader(soapEnvelope);
            Document doc = soapEnvelope.getAsDocument();

            // Header- and CountingContext-Elements must exist (@see #createCountingContextInSOAPHeader(soapEnvelope);)
            NodeList headers = doc.getElementsByTagNameNS(NS.SOAP_ENVELOPE_NAMESPACE, "Header");

//         Element header = (Element) headers.item(0);
//         Element countingContextElement = (Element) header.getElementsByTagNameNS(NS.ACCESS_CONTROL_PROTOTYP_NAMESPACE, Constants.ELEMENT_NAME_COUNTING_CONTEXT).item(0);
//         IFCountingContext countingContext = handlingInfo.getCountingContext();
//         Element tempCoordinationContext = countingContext.getCoordinationContext().getCoordinationContextElement();
//         Element coordinationContext = (Element) doc.adoptNode(tempCoordinationContext);
//         countingContextElement.appendChild(coordinationContext);

            Element header = null;
            if (headers.getLength() == 1) {
               if (logger.isDebugEnabled()) logger.debug(fn + " HEADER-Element already exists in ENVELOPE ...");
               header = (Element) headers.item(0);
               Element tempCoordinationContext = (Element) header.getElementsByTagNameNS(NS.ACCESS_CONTROL_PROTOTYP_NAMESPACE, Constants.ELEMENT_NAME_COUNTING_CONTEXT).item(0);
               header.removeChild(tempCoordinationContext);
            } else {
               //logger.error(fn + " more than one HEADER-Element found in ENVELOPE-Element!");
               throw new Exception(" zero or more than one HEADER-Element found in ENVELOPE!");
            }
            IFCountingContext countingContext = handlingInfo.getCountingContext();
            Element countingContextElement = countingContext.getContextElement();
            //System.out.println("BEFORE ADOPTATION: " + XMLUtils.ElementToString(countingContextElement));
            //@TODO without the next line the namespace-declarations rotate in a diffuse way !!!!???
            XMLUtils.ElementToString(countingContextElement);
            Node adoptedContextElement = doc.adoptNode(countingContextElement);
            //adoptedContextElement.appendChild(countingContext.getStepContext().makeContextElement(doc, countingContextElement));
            header.appendChild(adoptedContextElement);
            //System.out.println("ADOPTED: " + XMLUtils.ElementToString((Element)adoptedContextElement));
            String documentString = XMLUtils.DocumentToString(doc);
            //System.out.println(documentString);
            StreamSource source = new StreamSource(new StringReader(documentString));
            msg.getSOAPPart().setContent(source);
            //new Thread(new ClientHeaderContextEmbedder.DigestAgreementThread(countingContext, msg)).start();
         } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
         }
      } else {
         logger.fatal(fn + "Didn't perform operation because HandlingInfo FAILED!");
      }
      if (logger.isDebugEnabled()) logger.debug(fn + " <-- COUNTINGCONTEXTWRITER");
      MDC.remove(OPTION_LOG_INFO);
   }
}
