package com.broadsoft.clients.cap;

/*
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl;
import org.apache.xerces.jaxp.DocumentBuilderImpl;
import org.apache.xerces.parsers.*;
import org.apache.xerces.*;
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;

import org.apache.xerces.parsers.DOMParser;
import org.apache.xml.serialize.DOMSerializer;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;

public class MessageParser  {

  //private String clientInfo = "<clientInfo><loginId>\"id\"</loginId><clientData>\"resid\"</clientData></clientInfo>\n";
  private int messageLength;
  private DOMParser domp;
  private Parser xmlWriter;
  private volatile String commandType;
  private volatile String loginId;
  private volatile String responseId;
  private volatile String userUID;
  private volatile String userId;

  private volatile String failureCause;
  private volatile boolean hasErrors;
  private volatile boolean hasClientInfo;
  private Node clientInfoNode;
  private Node responseIdNode;


  public MessageParser() {
    hasClientInfo = false;
    hasErrors = false;
    commandType = "";
    loginId = "";
    responseId = "";
    userUID = "";
    userId = "";
    failureCause = "";
    try {
      domp = new DOMParser();
    }
    catch (Exception ex) {
      //System.out.println(ex);
    }
  }

  public boolean parse(String source) throws SAXException, IOException, Exception {
    initialize();
    messageLength = source.length();

    try {
      StringReader inReader = new StringReader(source);
      InputSource messageSource = new InputSource(inReader);
      messageSource.setEncoding(OpenClientServerConstants.XML_ENCODING);
      domp.parse(messageSource);
      Document doc = domp.getDocument();
      extractInfo( doc );
    }
    catch (IOException ex) {
      throw ex;
    }
    catch (SAXException ex) {
      throw ex;
    }
    catch( Exception ex ){
      throw ex;
    }
    return true;
  }

  //accessor functions
  public boolean isOCI() {
	  return false;
  }
  
  public String getLoginId() {
    return loginId;
  }

  public String getCommandType() {
    return commandType;
  }

  public String getResponseId() {
    return responseId;
  }

  public boolean hasErrors(){
    return hasErrors;
  }

  public boolean hasClientInfo(){
    return hasClientInfo;
  }

  public String getUserId(){
    return userId;
  }

  public String getUserUID(){
    return userUID;
  }
  public String getFailureCause(){
    return failureCause;
  }


  public String getText(){
    try{
      Document thisDoc = domp.getDocument();
      XMLSerializer ser = new XMLSerializer();
      DOMSerializer domSer = null;
      int msgLen = messageLength + 128;
      Integer size = new Integer(msgLen);
      ByteArrayOutputStream ByteOS = new ByteArrayOutputStream(size.intValue());
      ser.setOutputByteStream(ByteOS);
      ser.serialize(thisDoc);
      String modifiedMessage = ByteOS.toString();
      return modifiedMessage;
    }
    catch (IOException ex) {
      return null;
    }
    catch (DOMException ex) {
      return null;
    }
    catch (NullPointerException nex) {
      //System.out.println("MessageParser: NullPointerException " +
      //                   nex.getMessage());
      return null;
    }
  }

  private void extractInfo( Node node ){
    Node child = null;

    try {
      if (node==null) {
        return;
      }

      if( node.getNodeType() == Node.ELEMENT_NODE) {
        String nodeName = node.getNodeName();
        if( hasClientInfo()==false ){
          if( nodeName.compareTo( BWServiceConstants.OSS_MSG_TAG_CLIENTINFO)==0 ){
            setRequiredNodeValue(node, nodeName, "");
          }
        }
        if (node.hasAttributes()) {
          // get all the attributes of the node
          NamedNodeMap attributes = node.getAttributes();
          int nSize = attributes.getLength();

          for (int i = 0; i < nSize; ++i) {
            Attr attributeNode = (Attr)attributes.item(i);
            // get attribute name
            String tempName = attributeNode.getName();
            // get attribute value
            String tempValue = attributeNode.getValue();
            setRequiredNodeValue( attributeNode, tempName, tempValue);
          }
        }
        if (node.hasChildNodes()) {
          Node tempNode = node.getFirstChild();
          if (tempNode.getNodeType() == Node.TEXT_NODE) {
            //get attribute name
            String tempName = node.getNodeName();
            //get attribute value
            String tempValue = tempNode.getNodeValue();
            setRequiredNodeValue( node, tempName, tempValue);
          }
        }
      }

      for (child=node.getFirstChild();child!=null;child=child.getNextSibling()){
        extractInfo(child);
      }

    }
    catch (Exception ex) {
      return ;
    }
  }

  public boolean removeResponseId(){
    if( domp==null||clientInfoNode==null || responseIdNode==null ){
      return false;
    }
    clientInfoNode.removeChild(responseIdNode);
    return true;
  }

  public boolean addReponseId( String responseId ){
    if( domp==null||clientInfoNode==null ){
      return false;
    }
    Document doc = domp.getDocument();
    if( doc==null){
      return false;
    }
    Element responseNode = doc.createElement( BWServiceConstants.RESPONSE_ID );
    if( responseNode==null ){
      return false;
    }
    Text txtNode = doc.createTextNode(responseId);
    if( txtNode==null ){
      return true;
    }
    responseNode.appendChild(txtNode);
    clientInfoNode.appendChild(responseNode);
    return true;
  }

  private boolean setRequiredNodeValue( Node node, String nodeName, String nodeValue ){

    if( nodeName.compareTo( BWServiceConstants.OSS_MSG_TAG_CLIENTINFO)==0 ){
      hasClientInfo = true;
      clientInfoNode = node;
      return true;
    }
    else if( nodeName.compareTo(BWServiceConstants.OSS_MSG_TAG_LOGIN_ID )==0 ){
      loginId = nodeValue;
      return true;
    }
    else if( nodeName.compareTo( BWServiceConstants.RESPONSE_ID )==0 ){
      responseId = nodeValue;
      responseIdNode = node;
      return true;
    }
    else if( nodeName.compareTo( BWServiceConstants.OSS_MSG_ATTR_COMMAND_TYPE )==0 ){
      commandType = nodeValue;
      //System.out.println("has commandtype: " + commandType);
      return true;
    }
    else if( nodeName.compareTo(BWServiceConstants.ERROR)==0 ){
      //System.out.println("has errors");
      hasErrors = true;
      return true;
    }
    else if( nodeName.compareTo( BWServiceConstants.MSG_ATTR_USER_UID )==0 ){
      userUID = nodeValue;
      return true;
    }
    else if( nodeName.compareTo( BWServiceConstants.MSG_ATTR_FAILURE_CAUSE)==0 ){
      failureCause = nodeValue;
      return true;
    }
    else if( nodeName.compareTo( BWServiceConstants.MSG_TAG_ID)==0 ){
      userId = nodeValue;
      return true;
    }

    return true;
  }

  private void initialize() {
    hasClientInfo = false;
    hasErrors = false;
    commandType = "";
    loginId = "";
    responseId = "";
  }

}

/*
   <?xml version="1.0" encoding="UTF-8"?>
   <BroadsoftDocument protocol="OSSP" version="11.1">
   <clientInfo><loginId></loginId>
   <clientData>
   </clientData>
   </clientInfo>
   <command commandType="requestAuthentication">
   <commandData>
   <loginInfo>
   <loginId>userid1</loginId>
   </loginInfo>
   </commandData>
   </command></BroadsoftDocument>

 <?xml version="1.0" encoding="ISO-8859-1"?>
 <BroadsoftDocument protocol="OSSP" version="11.1"><clientInfo><loginId></loginId><clientData></clientData></clientInfo><command commandType="requestAuthentication"><transactionId>5</transactionId><result>0</result><commandData><loginInfo><loginId>userid1</loginId><nonce>1094834571421</nonce><algorithm>MD5</algorithm></loginInfo></commandData></command></BroadsoftDocument>

 */
/*
  <BroadsoftDocument protocol="OSSP" version="11.1">
 <clientInfo><
 loginId>userid1</loginId>
 <clientData>1234</clientData>
 </clientInfo>
*/
