/*
 * Copyright (c) 2008, PRODYNA AG, Germany. All rights reserved. Created 09.01.2008
 */

package classcastexceptiontest.process;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.ejb.Remote;
import javax.ejb.Stateless;

import org.apache.log4j.Logger;
import org.jboss.annotation.ejb.RemoteBinding;

import classcastexceptiontest.process.Process;
import classcastexceptiontest.process.ProcessBinding;
import classcastexceptiontest.process.RequestMsg;
import classcastexceptiontest.process.ResponseMsg;


/**
 * ProcessImpl
 * 
 * @author Andreas Heizenreder (PRODYNA AG)
 * @version $Id: ProcessImpl.java,v 1.1 2008/08/22 15:27:08 aheizenreder Exp $
 */
@Stateless
@Remote(Process.class)
@RemoteBinding(jndiBinding = ProcessBinding.JNDI_BINDING_PROCESS)
public class ProcessImpl implements Process {

    private Logger logger = Logger.getLogger(ProcessImpl.class);
    
    private static final int WATING_TIME_OUT = 5000;
    
    private static final String datePattern = "yyyy-MM-dd HH:mm:ss:SSS";

    private static int requestCount = 0;
    
    private static int waitingThreadsCount = 0;
    
    private static Object lock = new Object();

    public ResponseMsg doProcess(RequestMsg rq) {
        logger.debug("START doProcess() ...");
        
        requestCount++;
        logger.debug("Starting "+requestCount+" request");
        ResponseMsg response = null;
        SimpleDateFormat dateFormater = new SimpleDateFormat(datePattern);
        Date requestTime = new Date(System.currentTimeMillis());
        String requestTimeStr = dateFormater.format(requestTime);

        String requestData = rq.getRequestData();
        logger.debug("Request data: "+requestData);
        
        StringBuffer responseDataBuffer = new StringBuffer();
        responseDataBuffer.append("Request(");
        responseDataBuffer.append(requestTimeStr);
        responseDataBuffer.append("): ");
        responseDataBuffer.append(requestData);

        try {
            if (requestCount % 2 == 0) {
                synchronized (lock) {
                    // by odd requests wait until next request is ready
                    logger.debug("Odd request: Wait for the next (or time out after "+WATING_TIME_OUT+")!");
                    waitingThreadsCount = waitingThreadsCount + 1;
                    lock.wait(WATING_TIME_OUT);
                    waitingThreadsCount = waitingThreadsCount - 1;
                    logger.debug("waited thread is again running");
                }
            } else {
                synchronized(lock) {
                    if ( waitingThreadsCount > 0 ) {
                        logger.debug("notify waiting threads");
                        lock.notifyAll();
                    }
                }
            }
        } catch (InterruptedException ie) {
            // do nothing when interrupted
            logger.info("waiting threas was interupted");
        }

        Date responseTime = new Date(System.currentTimeMillis());
        String responseTimeStr = dateFormater.format(responseTime);
        responseDataBuffer.append("\nResponse(");
        responseDataBuffer.append(responseTimeStr);
        responseDataBuffer.append("): Done");

        response = new ResponseMsg();
        response.setResponseData(responseDataBuffer.toString());
        
        logger.debug("END doProcess()");
        return response;
    }
}
