

package gov.va.med.cds.util;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;


public class PerformanceLog
    implements
        PerformanceLogMBeanInterface,
        ApplicationContextAware
{
    private Log performanceLogger = LogFactory.getLog( PerformanceLog.class );
    public static final String STATUS_SUCCESS = "succeeded";
    public static final String STATUS_FAIL = "failed";
    private boolean enabled = false;

    private static PerformanceLog instance;

    private static ApplicationContext applicationContext;


    public void setApplicationContext( ApplicationContext appContext )
        throws BeansException
    {
        applicationContext = appContext;
        instance = null; /// in the event that the application context reloads, then the instance will also need to be reloaded
    }


    /** in order to eliminate the overhead of the spring lookup, the PerformanceLog.getInstance() provides access to the singleton performanceLog bean loaded in the application's spring context.  
     * 
     * @return
     */
    public static PerformanceLog getInstance( )
    {
        if ( instance != null )
            return instance;

        /// perform a lookup in the Spring context just one time and set it as the instance for use in future lookups
        //instance = (PerformanceLog)ApplicationContextProvider.getApplicationContext().getBean("performanceLog");

        if ( applicationContext == null )
        {
            instance = new PerformanceLog(); /// for testing purposes, when the application context is not available, then the singleton is just given a new instance without spring awareness...
            return instance;
        }
        instance = ( PerformanceLog )applicationContext.getBean( "performanceLog" );
        return instance;
    }


    public PerformanceLog( )
    {
    }


    public String logFinishTime( long startTime, long finishTime, String keywords, String domainEntryPoint, String templateId, String requestId,
                    String siteId, boolean succeeded, String tier )
    {
        if ( !enabled )
            return null;
        if ( performanceLogger.isInfoEnabled() )
        {
            if ( finishTime < startTime )
                throw new IllegalArgumentException( "finishTime argument cannot be less than startTime argument" );
            if ( finishTime < 0 )
                throw new IllegalArgumentException( "finishTime argument cannot be negative" );
            if ( startTime < 0 )
                throw new IllegalArgumentException( "startTime argument cannot be negative" );
            String status = succeeded ? STATUS_SUCCESS : STATUS_FAIL;
            String message = buildCsvMessage( startTime, finishTime, keywords, domainEntryPoint, templateId, requestId, siteId, status, tier );
            performanceLogger.info( message );
            return message;
        }
        return null;
    }


    private String buildCsvMessage( long startTime, long finishTime, String keywords, String domainEntryPoint, String templateId, String requestId,
                    String siteId, String status, String tier )

    {
        double durationInSeconds = ( finishTime - startTime ) / 1000.0;

        if ( keywords.indexOf( "," ) != -1 )
            keywords = "\"" + keywords + "\"";

        String message = keywords + "," + domainEntryPoint + "," + templateId + "," + requestId + "," + siteId + "," + startTime + "," + finishTime
                        + "," + durationInSeconds + "," + status + "," + tier;
        return message;
    }


    @Override
    public boolean isEnabled( )
    {
        return enabled;
    }


    @Override
    public void setEnabled( boolean b )
    {
        enabled = b;
    }

      public boolean isInfoEnabled( )
      {
          if ( !enabled) return false;  /// the MBean value takes precedence over the log4j config
          return performanceLogger.isInfoEnabled();
      }

}
