

package gov.va.med.cds.mediator.work;


import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.exceptionframework.ExceptionInfo;
import gov.va.med.cds.exceptionframework.ExceptionUtil;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class MapBackedWorkState
    implements
        WorkStateInterface
{
    private final Log logger = LogFactory.getLog( MapBackedWorkState.class );

    public static final String APPLICATION_NAME = "Message Mediator";

    private Map<String, Object> data = new Hashtable<String, Object>();

    private List<Exception> messageMediatorExceptionList = new LinkedList<Exception>();


    public boolean isWorkStateRegistered( String stateName )
    {

        return this.data.get( stateName ) == null ? false : true;

    }


    public Object locateWorkState( String stateName )
        throws WorkStateException
    {
        Object value = this.data.get( stateName );
        if ( value == null )
        {
            throw new WorkStateException( ErrorCodeEnum.WORK_STATE_EXPECTED_DATA_NOT_PRESENT_EXCEPTION, stateName );
        }

        return value;
    }


    public void registerWorkState( String stateName, Object stateData )
        throws WorkStateException
    {
        if ( this.data.containsKey( stateName ) )
        {
            throw new WorkStateException( ErrorCodeEnum.WORK_STATE_DUPLICATE_DATA_EXCEPTION, stateName );
        }

        this.data.put( stateName, stateData );
    }


    /*
     * Message Mediator exceptions are stored to provide information on error scenarios
     * 
     * @param messageMediatorExceptionList is the list of all exceptions that occur in Message Mediator module
     */
    public void addException( Exception messageMediatorException )
    {
        this.messageMediatorExceptionList.add( messageMediatorException );
        logException( messageMediatorException );
    }


    public List<Exception> getExceptions( )
    {
        return messageMediatorExceptionList;
    }


    public String getFormattedExceptionDetail( )
    {
        Exception[] exceptions = ( Exception[] )this.messageMediatorExceptionList.toArray( new Exception[] {} );
        StringBuilder sbFormatted = new StringBuilder( "Mediator Error Detail: " );

        for ( int i = 0; i < exceptions.length; i++ )
        {
            sbFormatted.append( '(' ).append( i + 1 ).append( ')' ).append( exceptions[i].getMessage() );
            if ( i < ( exceptions.length - 1 ) )
            {
                sbFormatted.append( ", " );
            }
        }

        return sbFormatted.toString();
    }


    public int getExceptionCount( )
    {
        return this.messageMediatorExceptionList.size();
    }


    private ExceptionInfo populateExceptionInfo( Exception exception, String clientMessage )
    {
        ExceptionInfo exceptionInfo = new ExceptionInfo();

        exceptionInfo.setClientMessage( clientMessage );
        exceptionInfo.setException( exception );

        return exceptionInfo;
    }


    private void logException( Exception e )
    {
        String messageControlId = getWorkStateData( "MSG-CTRL-ID" );
        String sendingApplication = getWorkStateData( "SENDING-APPLICATION" );

        if ( ( sendingApplication == null ) || ( messageControlId == null ) )
        {
            ExceptionUtil.logException( populateExceptionInfo( e, e.getMessage() ), logger, e.getMessage(), null, null,
                            MapBackedWorkState.APPLICATION_NAME );
        }
        else
        {
            ExceptionUtil.logException( populateExceptionInfo( e, e.getMessage() ), logger, e.getMessage(), sendingApplication, messageControlId,
                            MapBackedWorkState.APPLICATION_NAME );
        }

    }


    private String getWorkStateData( String workStateData )
    {
        return ( String )this.data.get( workStateData );
    }
}
