

package gov.va.med.cds.response.vhim400;


import static gov.va.med.cds.exceptionframework.LoggingSeverity.FATAL;
import gov.va.med.cds.exceptionframework.ExceptionInfo;
import gov.va.med.cds.exceptionframework.LoggingSeverity;
import gov.va.med.cds.request.ErrorSectionHelperInterface;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


public class NestedErrorSectionHelper implements ErrorSectionHelperInterface
{

    @Override
    public Document buildErrorSection( Document clinicalDataDocument, ExceptionInfo exceptionInfo, String requestId )
    {
        Element errorSectionElement = clinicalDataDocument.getRootElement().element( "errorSection" );

        if ( errorSectionElement == null )
        {
            errorSectionElement = DocumentHelper.createElement( "errorSection" );
            clinicalDataDocument.getRootElement().add( errorSectionElement );
        }

        addErrorsToErrorSection( errorSectionElement, exceptionInfo, requestId );

        return clinicalDataDocument;
    }


    @Override
    public int getErrorCount( ErrorType errorType, Document clinicalDataDocument )
    {
        Element errorSection = clinicalDataDocument.getRootElement().element( "errorSection" );
        if ( errorSection != null )
        {
            int warnings = errorSection.element( "warnings" ).elements( "warning" ).size();
            int errors = errorSection.element( "errors" ).elements( "error" ).size();
            int fatals = errorSection.element( "fatalErrors" ).elements( "fatalError" ).size();

            switch ( errorType )
            {
            case WARNING:
                return warnings;
            case ERROR:
                return errors;
            case FATAL:
                return fatals;
            case ALL:
            default:
                return warnings + errors + fatals;
            }
        }

        return 0;
    }


    private void addErrorsToErrorSection( Element errorSectionElement, ExceptionInfo exceptionInfo, String requestId )
    {

        String errorsElementName = getErrorsElementName( exceptionInfo.getErrorCode().getLoggingSeverity() );
        Element errorsElement = errorSectionElement.element( errorsElementName );

        if ( errorsElement == null )
        {
            errorsElement = getErrorsElementForSeverity(exceptionInfo.getErrorCode().getLoggingSeverity());
            errorSectionElement.add( errorsElement );
        }        
        
        Element errorElement = getErrorElementForSeverity( exceptionInfo.getErrorCode().getLoggingSeverity() );
        errorElement.addElement( "errorId" ).addText( requestId );
        errorElement.addElement( "exception" ).addText( exceptionInfo.getException().getClass().getName() );
        errorElement.addElement( "exceptionMessage" ).addText( exceptionInfo.getException().getMessage() );
        errorElement.addElement( "errorCode" ).addText( exceptionInfo.getErrorCode().name() );
        errorElement.addElement( "displayMessage" ).addText( exceptionInfo.getClientMessage() );        
        
        
        errorsElement.add( errorElement );
    }


    private Element getErrorsElementForSeverity( LoggingSeverity loggingSeverity)
    {
        if ( loggingSeverity == null )
        {
            loggingSeverity = FATAL;
        }
        switch ( loggingSeverity )
        {
        case WARNING:
            return DocumentHelper.createElement( "warnings" );
        case ERROR:
            return DocumentHelper.createElement( "errors" );
        case FATAL:
        default:
            return DocumentHelper.createElement( "fatalErrors" );
        }
    }


    private Element getErrorElementForSeverity( LoggingSeverity loggingSeverity )
    {
        if ( loggingSeverity == null )
        {
            loggingSeverity = FATAL;
        }
        switch ( loggingSeverity )
        {
        case WARNING:
            return DocumentHelper.createElement( "warning" );
        case ERROR:
            return DocumentHelper.createElement( "error" );
        case FATAL:
        default:
            return DocumentHelper.createElement( "fatalError" );
        }
    }
    
    private String getErrorsElementName( LoggingSeverity loggingSeverity )
    {
        if ( loggingSeverity == null )
        {
            loggingSeverity = FATAL;
        }
        switch ( loggingSeverity )
        {
        case WARNING:
            return "warnings";
        case ERROR:
            return "errors";
        case FATAL:
        default:
            return "fatalErrors";
        }
    }    
    

}