package be.iminds.ilabt.jfed.call_log_output;

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;

import static be.iminds.ilabt.jfed.call_log_output.SerializableApiCallDetailsConstants.*;
import static be.iminds.ilabt.jfed.lowlevel.connection.JFedConnection.ProxyInfo;
import static be.iminds.ilabt.jfed.lowlevel.connection.JFedConnection.SshProxyInfo;
import static java.time.ZoneId.systemDefault;
import static java.time.ZonedDateTime.ofInstant;
import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;

/**
 * User: twalcari
 * Date: 4/8/2015
 * Time: 09:27
 */
public class SerializableApiCallDetailsWriter {

    public static void writeApiCallDetails(SerializableApiCallDetails apiCallDetails, XMLEventWriter xtw, XMLEventFactory eventFactory) throws XMLStreamException {
        xtw.add(eventFactory.createStartElement(Q_CALL, null, null));

        xtw.add(eventFactory.createAttribute(Q_CALL_ID, Integer.toString(apiCallDetails.getId())));

        /*
        Connection details
         */

        xtw.add(eventFactory.createStartElement(Q_AUTHORITY_NAME, null, null));
        xtw.add(eventFactory.createCharacters(apiCallDetails.getAuthorityName()));
        xtw.add(eventFactory.createEndElement(Q_AUTHORITY_NAME, null));

        xtw.add(eventFactory.createStartElement(Q_AUTHORITY_URN, null, null));
        xtw.add(eventFactory.createCharacters(apiCallDetails.getAuthorityUrn()));
        xtw.add(eventFactory.createEndElement(Q_AUTHORITY_URN, null));

        if (apiCallDetails.getBaseServerUrl() != null) {
            xtw.add(eventFactory.createStartElement(Q_BASE_SERVER_URL, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getBaseServerUrl()));
            xtw.add(eventFactory.createEndElement(Q_BASE_SERVER_URL, null));
        }

        if (apiCallDetails.getCallServerUrl() != null) {
            xtw.add(eventFactory.createStartElement(Q_CALL_SERVER_URL, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getCallServerUrl()));
            xtw.add(eventFactory.createEndElement(Q_CALL_SERVER_URL, null));
        }

        if (apiCallDetails.getProxyInfo() != null) {
            ProxyInfo proxyInfo = apiCallDetails.getProxyInfo();

            xtw.add(eventFactory.createStartElement(Q_PROXY_INFO, null, null));

            xtw.add(eventFactory.createStartElement(Q_HOSTNAME, null, null));
            xtw.add(eventFactory.createCharacters(proxyInfo.getHostname()));
            xtw.add(eventFactory.createEndElement(Q_HOSTNAME, null));

            xtw.add(eventFactory.createStartElement(Q_PORT, null, null));
            xtw.add(eventFactory.createCharacters(Integer.toString(proxyInfo.getPort())));
            xtw.add(eventFactory.createEndElement(Q_PORT, null));

            if (proxyInfo instanceof SshProxyInfo) {
                SshProxyInfo sshProxyInfo = (SshProxyInfo) proxyInfo;

                xtw.add(eventFactory.createStartElement(Q_USERNAME, null, null));
                xtw.add(eventFactory.createCharacters(sshProxyInfo.getUsername()));
                xtw.add(eventFactory.createEndElement(Q_USERNAME, null));

                xtw.add(eventFactory.createStartElement(Q_HOST_KEY, null, null));
                xtw.add(eventFactory.createCharacters(sshProxyInfo.getHostKey()));
                xtw.add(eventFactory.createEndElement(Q_HOST_KEY, null));
            }

            xtw.add(eventFactory.createEndElement(Q_PROXY_INFO, null)); //proxy_info
        }

        xtw.add(eventFactory.createStartElement(Q_CONNECTION_USER_URN, null, null));
        if (apiCallDetails.getConnectionSslAuthUserUrn() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionSslAuthUserUrn()));
        xtw.add(eventFactory.createEndElement(Q_CONNECTION_USER_URN, null));

        if (apiCallDetails.getConnectionBasicHttpAuthUsername() != null) {
            xtw.add(eventFactory.createStartElement(Q_CONNECTION_HTTP_BASIC_AUTHENTICATION_USERNAME, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionBasicHttpAuthUsername()));
            xtw.add(eventFactory.createEndElement(Q_CONNECTION_HTTP_BASIC_AUTHENTICATION_USERNAME, null));
        }

        if (apiCallDetails.getConnectionType() != null) {
            xtw.add(eventFactory.createStartElement(Q_CONNECTION_CONFIG_AUTH_METHOD, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionAuthenticationMethod()));
            xtw.add(eventFactory.createEndElement(Q_CONNECTION_CONFIG_AUTH_METHOD, null));
        }
        if (apiCallDetails.getConnectionType() != null) {
            xtw.add(eventFactory.createStartElement(Q_CONNECTION_CONFIG_PROTOCOL, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionProtocol()));
            xtw.add(eventFactory.createEndElement(Q_CONNECTION_CONFIG_PROTOCOL, null));
        }
        if (apiCallDetails.getConnectionType() != null) {
            xtw.add(eventFactory.createStartElement(Q_CONNECTION_CONFIG_TYPE, null, null));
//            assert !apiCallDetails.getConnectionType().trim().isEmpty();
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionType()));
            xtw.add(eventFactory.createEndElement(Q_CONNECTION_CONFIG_TYPE, null));
        }

        xtw.add(eventFactory.createStartElement(Q_CONNECTION_ID, null, null));
        if (apiCallDetails.getConnectionId() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionId()));
        xtw.add(eventFactory.createEndElement(Q_CONNECTION_ID, null));

        xtw.add(eventFactory.createStartElement(Q_CONNECTION_USER_CERTS, null, null));
        if (apiCallDetails.getConnectionSslAuthUserCertificates() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getConnectionSslAuthUserCertificates()));
        xtw.add(eventFactory.createEndElement(Q_CONNECTION_USER_CERTS, null));

        /*
        HTTP-level
         */

        xtw.add(eventFactory.createStartElement(Q_HTTP_REQUEST_LINE, null, null));
        if (apiCallDetails.getHttpRequestStatusLine() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpRequestStatusLine()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_REQUEST_LINE, null));

        xtw.add(eventFactory.createStartElement(Q_HTTP_REQUEST_HEADERS, null, null));
        if (apiCallDetails.getHttpRequestHeaders() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpRequestHeaders()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_REQUEST_HEADERS, null));

        xtw.add(eventFactory.createStartElement(Q_HTTP_REQUEST, null, null));
        if (apiCallDetails.getHttpRequest() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpRequest()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_REQUEST, null));

        xtw.add(eventFactory.createStartElement(Q_HTTP_STATUS_LINE, null, null));
        if (apiCallDetails.getHttpResponseStatusLine() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpResponseStatusLine()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_STATUS_LINE, null));

        xtw.add(eventFactory.createStartElement(Q_HTTP_RESPONSE_HEADERS, null, null));
        if (apiCallDetails.getHttpResponseStatusLine() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpResponseStatusLine()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_RESPONSE_HEADERS, null));

        xtw.add(eventFactory.createStartElement(Q_HTTP_REPLY, null, null));
        if (apiCallDetails.getHttpResponse() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getHttpResponse()));
        xtw.add(eventFactory.createEndElement(Q_HTTP_REPLY, null));

        /*
        API-level
         */


        xtw.add(eventFactory.createStartElement(Q_API_NAME, null, null));
        if (apiCallDetails.getApiName() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getApiName()));
        xtw.add(eventFactory.createEndElement(Q_API_NAME, null));


        xtw.add(eventFactory.createStartElement(Q_JAVA_METHOD_NAME, null, null));
        if (apiCallDetails.getJavaMethodName() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getJavaMethodName()));
        xtw.add(eventFactory.createEndElement(Q_JAVA_METHOD_NAME, null));


        xtw.add(eventFactory.createStartElement(Q_GENI_METHOD_NAME, null, null));
        if (apiCallDetails.getGeniMethodName() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getGeniMethodName()));
        xtw.add(eventFactory.createEndElement(Q_GENI_METHOD_NAME, null));


        xtw.add(eventFactory.createStartElement(Q_METHOD_PARAMETERS, null, null));
        if (apiCallDetails.getMethodParameters() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getMethodParameters()));
        xtw.add(eventFactory.createEndElement(Q_METHOD_PARAMETERS, null));


        /*
        XML-RPC-level
         */

        xtw.add(eventFactory.createStartElement(Q_XMLRPC_REQUEST, null, null));
        if (apiCallDetails.getXmlRpcRequestJsonString() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getXmlRpcRequestJsonString()));
        xtw.add(eventFactory.createEndElement(Q_XMLRPC_REQUEST, null));


        xtw.add(eventFactory.createStartElement(Q_XMLRPC_REPLY, null, null));
        if (apiCallDetails.getXmlRpcResponseJsonString() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getXmlRpcResponseJsonString()));
        xtw.add(eventFactory.createEndElement(Q_XMLRPC_REPLY, null));


        /*
        GENI-values
         */


        xtw.add(eventFactory.createStartElement(Q_GENI_VALUE, null, null));
        if (apiCallDetails.getXmlRpcGeniResponseValue() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getXmlRpcGeniResponseValue()));
        xtw.add(eventFactory.createEndElement(Q_GENI_VALUE, null));

        xtw.add(eventFactory.createStartElement(Q_GENI_OUTPUT, null, null));
        if (apiCallDetails.getXmlRpcGeniResponseOutput() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getXmlRpcGeniResponseOutput()));
        xtw.add(eventFactory.createEndElement(Q_GENI_OUTPUT, null));

        xtw.add(eventFactory.createStartElement(Q_GENI_CODE, null, null));
        if (apiCallDetails.getXmlRpcGeniResponseCode() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getXmlRpcGeniResponseCode()));
        xtw.add(eventFactory.createEndElement(Q_GENI_CODE, null));


        xtw.add(eventFactory.createStartElement(Q_GENI_RESPONSE_CODE, null, null));
        if (apiCallDetails.getGeniResponseCode() != null)
            xtw.add(eventFactory.createCharacters(Integer.toString(apiCallDetails.getGeniResponseCode())));
        xtw.add(eventFactory.createEndElement(Q_GENI_RESPONSE_CODE, null));

        xtw.add(eventFactory.createStartElement(Q_GENI_RESPONSE_CODE_DESCRIPTION, null, null));
        if (apiCallDetails.getGeniResponseCodeDescription() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getGeniResponseCodeDescription()));
        xtw.add(eventFactory.createEndElement(Q_GENI_RESPONSE_CODE_DESCRIPTION, null));

        xtw.add(eventFactory.createStartElement(Q_GENI_CODE_IS_SUCCESS, null, null));
        if (apiCallDetails.getGeniResponseCodeIsSuccess() != null)
            xtw.add(eventFactory.createCharacters(Boolean.toString(apiCallDetails.getGeniResponseCodeIsSuccess())));
        xtw.add(eventFactory.createEndElement(Q_GENI_CODE_IS_SUCCESS, null));

        xtw.add(eventFactory.createStartElement(Q_GENI_RESPONSE_OUTPUT, null, null));
        if (apiCallDetails.getGeniResponseOutput() != null)
            xtw.add(eventFactory.createCharacters(apiCallDetails.getGeniResponseOutput()));
        xtw.add(eventFactory.createEndElement(Q_GENI_RESPONSE_OUTPUT, null));

        /*
        Raw output
         */

        xtw.add(eventFactory.createStartElement(Q_RAW_RESPONSE, null, null));
        if (apiCallDetails.getRawValue() != null) {
            xtw.add(eventFactory.createCharacters(apiCallDetails.getRawValue()));
        }
        xtw.add(eventFactory.createEndElement(Q_RAW_RESPONSE, null));

        /*
        Additional info
         */
        xtw.add(eventFactory.createStartElement(Q_START_TIME, null, null));
        if (apiCallDetails.getStartTime() != null)
            xtw.add(eventFactory.createCharacters(ISO_OFFSET_DATE_TIME.format(ofInstant(apiCallDetails.getStartTime().toInstant(), systemDefault()))));
        xtw.add(eventFactory.createEndElement(Q_START_TIME, null));    //start_time


        xtw.add(eventFactory.createStartElement(Q_END_TIME, null, null));

        if (apiCallDetails.getStopTime() != null)
            xtw.add(eventFactory.createCharacters(ISO_OFFSET_DATE_TIME.format(ofInstant(apiCallDetails.getStopTime().toInstant(), systemDefault()))));
        xtw.add(eventFactory.createEndElement(Q_END_TIME, null));   //end_time

        if (apiCallDetails.getProtogeniSpewLogUrl() != null) {
            xtw.add(eventFactory.createStartElement(Q_PROTOGENI_SPEW_LOG_URL, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getProtogeniSpewLogUrl()));
            xtw.add(eventFactory.createEndElement(Q_PROTOGENI_SPEW_LOG_URL, null));
        }

        if (apiCallDetails.getExceptionString() != null) {
            xtw.add(eventFactory.createStartElement(Q_EXCEPTION, null, null));
            xtw.add(eventFactory.createCharacters(apiCallDetails.getExceptionString()));
            xtw.add(eventFactory.createEndElement(Q_EXCEPTION, null));
        }


        xtw.add(eventFactory.createEndElement(Q_CALL, null)); //call
    }

}
