/*******************************************************************************
 * Copyright (c) 2007, 2012 Innoopract Informationssysteme GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Innoopract Informationssysteme GmbH - initial API and implementation
 *    EclipseSource - ongoing development
 ******************************************************************************/
package org.eclipse.rap.rwt.internal.uicallback;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingListener;

import junit.framework.TestCase;

import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.rap.rwt.internal.service.ServiceContext;
import org.eclipse.rap.rwt.internal.service.ServiceStore;
import org.eclipse.rap.rwt.internal.uicallback.UICallBackManager;
import org.eclipse.rap.rwt.internal.uicallback.UICallBackServiceHandler;
import org.eclipse.rap.rwt.lifecycle.PhaseId;
import org.eclipse.rap.rwt.lifecycle.ProcessActionRunner;
import org.eclipse.rap.rwt.testfixture.Fixture;
import org.eclipse.rap.rwt.testfixture.Message;
import org.eclipse.rap.rwt.testfixture.TestRequest;
import org.eclipse.rap.rwt.testfixture.TestResponse;
import org.eclipse.rap.rwt.testfixture.internal.NoOpRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.widgets.Display;


public class UICallBackManager_Test extends TestCase {
  public static final String SYS_PROP_SLEEP_TIME = "sleepTime";
  public static final String SYS_PROP_TIMER_EXEC_DELAY = "timerExecDelay";

  private static final int SLEEP_TIME;
  private static final int TIMER_EXEC_DELAY;

  private static final String ID_1 = "id_1";
  private static final String ID_2 = "id_2";
  private static final String RUN_ASYNC_EXEC = "run async exec|";
  private static final Runnable EMPTY_RUNNABLE = new NoOpRunnable();

  static {
    String sleepTimeProp = System.getProperty( SYS_PROP_SLEEP_TIME );
    SLEEP_TIME = sleepTimeProp == null ? 200 : Integer.parseInt( sleepTimeProp );
    String timerExecDelayProp = System.getProperty( SYS_PROP_TIMER_EXEC_DELAY );
    TIMER_EXEC_DELAY = timerExecDelayProp == null ? 5000 :Integer.parseInt( timerExecDelayProp );
  }

  private volatile String log = "";
  private Display display;
  private UICallBackManager manager;
  private UICallBackServiceHandler uiCallBackServiceHandler;

  @Override
  protected void setUp() throws Exception {
    Fixture.setUp();
    log = "";
    display  = new Display();
    manager = UICallBackManager.getInstance();
    uiCallBackServiceHandler = new UICallBackServiceHandler();
  }

  @Override
  protected void tearDown() throws Exception {
    Fixture.tearDown();
  }

  public void testWakeClient() throws InterruptedException {
    final Throwable[] uiCallBackServiceHandlerThrowable = { null };
    final ServiceContext context[] = { ContextProvider.getContext() };
    Thread thread = new Thread( new Runnable() {
      public void run() {
        ContextProvider.setContext( context[ 0 ] );
        Fixture.fakeResponseWriter();
        UICallBackServiceHandler uiCallBackServiceHandler = new UICallBackServiceHandler();
        try {
          manager.activateUICallBacksFor( "foo" );
          uiCallBackServiceHandler.service();
        } catch( Throwable thr ) {
          uiCallBackServiceHandlerThrowable[ 0 ] = thr;
        }
      }
    } );
    thread.start();
    Thread.sleep( SLEEP_TIME );
    if( uiCallBackServiceHandlerThrowable[ 0 ] != null ) {
      uiCallBackServiceHandlerThrowable[ 0 ].printStackTrace();
    }
    assertNull( uiCallBackServiceHandlerThrowable[ 0 ] );
    assertTrue( manager.isCallBackRequestBlocked() );

    manager.setHasRunnables( true );
    manager.wakeClient();
    thread.join();

    assertFalse( manager.isCallBackRequestBlocked() );
    assertFalse( thread.isAlive() );
  }

  public void testWaitOnUIThread() throws Exception {
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator();
    callBackRequestSimulator.sendRequest();

    display.wake();

    assertTrue( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator.exceptionOccured() );
    manager.releaseBlockedRequest();
  }

  public void testWaitOnBackgroundThread() throws Throwable {
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator();
    callBackRequestSimulator.sendRequest();
    assertTrue( manager.isCallBackRequestBlocked() );

    callDisplayWake();
    callBackRequestSimulator.waitForRequest();

    assertFalse( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator.exceptionOccured() );
  }

  // same test as above, but while UIThread running
  public void testWaitOnBackgroundThreadDuringLifecycle() throws Throwable {
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator();
    callBackRequestSimulator.sendRequest();
    assertTrue( manager.isCallBackRequestBlocked() );

    // assume that UIThread is currently running the life cycle
    manager.notifyUIThreadStart();
    callDisplayWake();
    manager.notifyUIThreadEnd();
    callBackRequestSimulator.waitForRequest();

    assertFalse( callBackRequestSimulator.exceptionOccured() );
    assertFalse( manager.isCallBackRequestBlocked() );
  }

  public void testAsyncExecWhileLifeCycleIsRunning() {
    fakeNewRequest();
    Fixture.fakePhase( PhaseId.READ_DATA );
    simulateAsyncExecDuringLifeCycle();
    Fixture.fakePhase( PhaseId.PROCESS_ACTION );
    display.readAndDispatch();
    assertTrue( manager.hasRunnables() );
    Fixture.executeLifeCycleFromServerThread();
    assertEquals( RUN_ASYNC_EXEC, log );
    assertFalse( manager.isCallBackRequestBlocked() );
  }

  public void testAsyncExecWithBackgroundAndLifeCycleRunnables() throws Throwable {
    // test unblocking in case of background addition of runnables
    simulateBackgroundAddition( ContextProvider.getContext() );
    // test runnables execution during lifecycle with interlocked additions
    fakeNewRequest();
    Fixture.fakePhase( PhaseId.READ_DATA );
    simulateAsyncExecDuringLifeCycle();
    Fixture.executeLifeCycleFromServerThread();
    assertFalse( manager.isCallBackRequestBlocked() );
    assertEquals( RUN_ASYNC_EXEC + RUN_ASYNC_EXEC + RUN_ASYNC_EXEC, log );
  }

  public void testCallBackRequestBlocking() throws Exception {
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator();
    callBackRequestSimulator.sendRequest();
    assertFalse( callBackRequestSimulator.exceptionOccured() );
    assertTrue( manager.isCallBackRequestBlocked() );
  }

  public void testCallBackRequestReleasing() throws Throwable {
    ServiceContext context = ContextProvider.getContext();
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator( context );
    callBackRequestSimulator.sendRequest();

    simulateBackgroundAddition( context );
    callBackRequestSimulator.waitForRequest();

    assertFalse( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator.isRequestRunning() );
    assertEquals( "", log );
  }

  public void testCallBackRequestIsReleasedOnSessionInvalidate() throws Exception {
    ServiceContext context = ContextProvider.getContext();
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator( context );
    callBackRequestSimulator.sendRequest();

    context.getSessionStore().getHttpSession().invalidate();
    callBackRequestSimulator.waitForRequest();

    TestResponse response = ( TestResponse )context.getResponse();
    Message message = new Message( response.getContent().trim() );
    assertEquals( 0, message.getOperationCount() );
    assertFalse( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator.isRequestRunning() );
    assertFalse( callBackRequestSimulator.exceptionOccured() );
  }

  public void testCallBackRequestIsReleasedWhenSessionExpires() throws Exception {
    HttpSession httpSession = ContextProvider.getSessionStore().getHttpSession();
    httpSession.setMaxInactiveInterval( 1 );
    HttpSessionBindingListener sessionListener = mock( HttpSessionBindingListener.class );
    httpSession.setAttribute( "listener", sessionListener );
    manager.setRequestCheckInterval( 10 );

    manager.activateUICallBacksFor( "id" );
    boolean success = manager.processRequest( ContextProvider.getResponse() );

    assertFalse( success );
  }

  public void testMultipleCallBackRequests() throws Exception {
    manager.setRequestCheckInterval( 20 );
    ServiceContext context1 = ContextProvider.getContext();
    CallBackRequestSimulator callBackRequestSimulator1 = new CallBackRequestSimulator( context1 );
    callBackRequestSimulator1.sendRequest();
    ServiceContext context2 = createServiceContext( new TestResponse() );
    CallBackRequestSimulator callBackRequestSimulator2 = new CallBackRequestSimulator( context2 );

    callBackRequestSimulator2.sendRequest();
    callBackRequestSimulator1.waitForRequest();

    TestResponse response = ( TestResponse )context1.getResponse();
    Message message = new Message( response.getContent().trim() );
    assertEquals( 0, message.getOperationCount() );
    assertTrue( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator1.exceptionOccured() );
    assertFalse( callBackRequestSimulator2.exceptionOccured() );
    assertFalse( callBackRequestSimulator1.isRequestRunning() );
    assertTrue( callBackRequestSimulator2.isRequestRunning() );
  }

  public void testCallBackRequestTerminatsWhenConnectionBreaks() throws Exception {
    manager.setRequestCheckInterval( 20 );
    TestResponse response = new TestResponse() {
      @Override
      public PrintWriter getWriter() throws IOException {
        PrintWriter failingWriter = mock( PrintWriter.class );
        when( new Boolean( failingWriter.checkError() ) ).thenReturn( Boolean.TRUE );
        return failingWriter;
      }
    };
    ServiceContext context2 = createServiceContext( response );
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator( context2 );
    callBackRequestSimulator.sendRequest();

    Thread.sleep( SLEEP_TIME );

    assertFalse( manager.isCallBackRequestBlocked() );
    callBackRequestSimulator.waitForRequest();
    assertFalse( callBackRequestSimulator.isRequestRunning() );
  }

  public void testAsyncExec() throws Throwable {
    Throwable[] uiCallBackServiceHandlerThrowable = { null };
    ServiceContext context = ContextProvider.getContext();
    // test runnables addition while no uiCallBack thread is not blocked
    CallBackRequestSimulator callBackRequestSimulator = new CallBackRequestSimulator( context );
    callBackRequestSimulator.sendRequest();

    manager.notifyUIThreadEnd();
    simulateBackgroundAddition( context );
    fakeNewRequest();
    Fixture.executeLifeCycleFromServerThread();
    // let request thread finish off and die
    callBackRequestSimulator.requestThread.join( 100 );

    assertNull( uiCallBackServiceHandlerThrowable[ 0 ] );
    assertFalse( manager.isCallBackRequestBlocked() );
    assertFalse( callBackRequestSimulator.isRequestRunning() );
    assertEquals( RUN_ASYNC_EXEC + RUN_ASYNC_EXEC, log );
  }

  public void testExceptionInAsyncExec() {
    Fixture.fakePhase( PhaseId.PROCESS_ACTION );
    final RuntimeException exception = new RuntimeException( "bad things happen" );
    Runnable runnable = new Runnable() {
      public void run() {
        throw exception;
      }
    };
    display.asyncExec( runnable );
    try {
      display.readAndDispatch();
      String msg
        = "Exception that occurs in an asynExec runnable must be wrapped "
        + "in an SWTException";
      fail( msg );
    } catch( SWTException e ) {
      assertEquals( SWT.ERROR_FAILED_EXEC, e.code );
      assertSame( exception, e.throwable );
    }
  }

  public void testTimerExec() throws Exception {
    Fixture.fakePhase( PhaseId.PROCESS_ACTION );
    Runnable runnable = mock( Runnable.class );
    display.timerExec( TIMER_EXEC_DELAY, runnable );
    Thread.sleep( TIMER_EXEC_DELAY + 50 );

    display.readAndDispatch();

    verify( runnable ).run();
  }

  // Ensure that runnables that were added via timerExec but should be executed
  // in the future are *not* executed on session shutdown
  public void testNoTimerExecAfterSessionShutdown() throws Exception {
    Runnable runnable = mock( Runnable.class );
    display.timerExec( TIMER_EXEC_DELAY, runnable );
    display.dispose();
    Thread.sleep( SLEEP_TIME );
    verifyZeroInteractions( runnable );
  }

  public void testRemoveAddedTimerExec() throws Exception {
    Runnable runnable = mock( Runnable.class );
    display.timerExec( TIMER_EXEC_DELAY, runnable );
    display.timerExec( -1, runnable );
    Thread.sleep( SLEEP_TIME );
    assertFalse( manager.hasRunnables() );
    verifyZeroInteractions( runnable );
  }

  public void testTimerExecActivatesUICallback() {
    display.timerExec( TIMER_EXEC_DELAY, mock( Runnable.class ) );

    assertTrue( UICallBackManager.getInstance().isUICallBackActive() );
  }

  public void testDispatchingTimerExecRunnableDeactivatesUICallback() throws Exception {
    Runnable runnable = mock( Runnable.class );
    display.timerExec( TIMER_EXEC_DELAY, runnable );

    Thread.sleep( TIMER_EXEC_DELAY + 50 );

    assertFalse( UICallBackManager.getInstance().isUICallBackActive() );
  }

  // This test ensures that addSync doesn't cause deadlocks
  public void testSyncExecBlock() throws Exception {
    Fixture.fakePhase( PhaseId.PROCESS_ACTION );
    final ServiceContext context = ContextProvider.getContext();
    // the code in bgRunnable simulates a bg-thread that calls Display#addSync
    Runnable bgRunnable = new Runnable() {
      public void run() {
        ContextProvider.setContext( context );
        Fixture.fakeResponseWriter();
        display.syncExec( EMPTY_RUNNABLE );
      }
    };
    // simulate a lot "parallel" bg-threads to provoke multi-threading problems
    List<Thread> bgThreads = new ArrayList<Thread>();
    for( int i = 0; i < 200; i++ ) {
      Thread bgThread = new Thread( bgRunnable, "Test-Bg-Thread " + i );
      bgThread.setDaemon( true );
      bgThread.start();
      display.readAndDispatch();
      bgThreads.add( bgThread );
    }
    // wait (hopefully long enough) until all bg-threads have done their work
    // (i.e. called addSync) and make sure all sync-runnables get executed
    Thread.sleep( SLEEP_TIME );
    while( display.readAndDispatch() ) {
      Thread.sleep( SLEEP_TIME );
    }
    // wait for all bgThreads to terminate
    for( int i = 0; i < bgThreads.size(); i++ ) {
      Thread bgThread = bgThreads.get( i );
      bgThread.join();
      display.readAndDispatch();
    }
    assertFalse( manager.hasRunnables() );
  }

  // This test ensures that SyncRunnable releases the blocked thread in case of
  // an exception
  public void testAddSyncWithExceptionInRunnable() throws Exception {
    Fixture.fakePhase( PhaseId.PROCESS_ACTION );
    final ServiceContext context = ContextProvider.getContext();
    final AtomicReference<SWTException> exceptionInBgThread = new AtomicReference<SWTException>();
    // the code in bgRunnable simulates a bg-thread that calls Display#addSync
    // and causes an exception in the runnable
    Runnable bgRunnable = new Runnable() {
      public void run() {
        ContextProvider.setContext( context );
        Fixture.fakeResponseWriter();
        Runnable causeException = new Runnable() {
          public void run() {
            throw new RuntimeException( "Exception in sync-runnable" );
          }
        };
        try {
          display.syncExec( causeException );
        } catch( SWTException e ) {
          exceptionInBgThread.set( e );
        }
      }
    };

    Thread bgThread = new Thread( bgRunnable );
    bgThread.setDaemon( true );
    bgThread.start();
    try {
      while( !display.readAndDispatch() ) {
        Thread.yield();
        Thread.sleep( SLEEP_TIME );
      }
      fail( "Exception from causeException-runnable must end up here" );
    } catch( SWTException expected ) {
    }
    Thread.sleep( SLEEP_TIME );
    assertNotNull( exceptionInBgThread.get() );
    assertFalse( bgThread.isAlive() );
  }

  public void testMustBlockCallBackRequest() {
    assertFalse( manager.mustBlockCallBackRequest() );
  }

  public void testMustBlockCallBackRequestWhenActive() {
    manager.activateUICallBacksFor( "foo" );
    assertTrue( manager.mustBlockCallBackRequest() );
  }

  public void testMustBlockCallBackRequestWhenActiveAndRunnablesPending() {
    manager.activateUICallBacksFor( "foo" );
    manager.setHasRunnables( true );
    assertFalse( manager.mustBlockCallBackRequest() );
  }

  public void testMustBlockCallBackRequestWhenDeactivatedAndRunnablesPending() {
    manager.setHasRunnables( true );
    assertFalse( manager.mustBlockCallBackRequest() );
  }

  public void testNeedActivationFromDifferentSession() throws Throwable {
    // test that on/off switching is managed in session scope
    manager.activateUICallBacksFor( ID_1 );
    final boolean[] otherSession = new boolean[ 1 ];
    Runnable runnable = new Runnable() {
      public void run() {
        Fixture.createServiceContext();
        new Display();
        otherSession[ 0 ] = UICallBackManager.getInstance().needsActivation();
      }
    };
    Fixture.runInThread( runnable );
    assertFalse( otherSession[ 0 ] );
  }

  public void testNeedActivationWithoutActivateCall() throws Exception {
    boolean needsActivation = manager.needsActivation();
    assertFalse( needsActivation );
  }

  public void testNeedActivationAfterDeactivate() throws Exception {
    manager.deactivateUICallBacksFor( ID_1 );
    assertFalse( manager.needsActivation() );
  }

  public void testNeedActivationWithDifferentIds() throws Exception {
    manager.activateUICallBacksFor( ID_1 );
    manager.activateUICallBacksFor( ID_2 );
    assertTrue( manager.needsActivation() );
  }

  public void testNeedActivationAfterActivateTwoDeactivateOne() throws Exception {
    manager.activateUICallBacksFor( ID_1 );
    manager.activateUICallBacksFor( ID_2 );
    manager.deactivateUICallBacksFor( ID_1 );
    assertTrue( manager.needsActivation() );
  }

  public void testNeedActivateTwice() throws Exception {
    manager.activateUICallBacksFor( ID_1 );
    manager.deactivateUICallBacksFor( ID_1 );
    manager.activateUICallBacksFor( ID_2 );
    assertTrue( manager.needsActivation() );
  }

  public void testNeedActivationWithActivateDeactivateAndPendingRunnables() throws Exception {
    manager.activateUICallBacksFor( ID_1 );
    display.asyncExec( EMPTY_RUNNABLE );
    manager.deactivateUICallBacksFor( ID_1 );
    assertTrue( manager.needsActivation() );
  }

  public void testNeedActivationWithPendingRunnablesDoesntEnableUICallback() throws Exception {
    display.asyncExec( EMPTY_RUNNABLE );
    assertFalse( manager.needsActivation() );
  }

  public void testIsSessionExpiredWithInfiniteSessionTimeout() {
    ContextProvider.getSessionStore().getHttpSession().setMaxInactiveInterval( -1 );

    boolean sessionExpired = UICallBackManager.isSessionExpired( 1, 2 );

    assertFalse( sessionExpired );
  }

  public void testIsSessionExpiredWhenSessionTimedOut() {
    ContextProvider.getSessionStore().getHttpSession().setMaxInactiveInterval( 10 );

    boolean sessionExpired = UICallBackManager.isSessionExpired( 1, 20000 );

    assertTrue( sessionExpired );
  }

  public void testIsSessionExpiredWhenSessionActive() {
    ContextProvider.getSessionStore().getHttpSession().setMaxInactiveInterval( 10 );

    boolean sessionExpired = UICallBackManager.isSessionExpired( 1, 9000 );

    assertFalse( sessionExpired );
  }

  public void testSetHasRunnablesWithoutStateInfo() {
    // Service handlers don't have a state info
    manager.activateUICallBacksFor( "foo" );
    Fixture.replaceServiceStore( null );

    try {
      manager.setHasRunnables( true );
    } catch( NullPointerException notExpected ) {
      fail();
    }
  }

  private void simulateBackgroundAddition( final ServiceContext serviceContext ) throws Throwable {
    Runnable runnable = new Runnable() {
      public void run() {
        ContextProvider.setContext( serviceContext );
        display.asyncExec( new AsyncExecRunnable() );
        display.asyncExec( new AsyncExecRunnable() );
      }
    };
    Fixture.runInThread( runnable );
  }

  private void simulateAsyncExecDuringLifeCycle() {
    ProcessActionRunner.add( new Runnable() {
      public void run() {
        Runnable target = new Runnable() {
          public void run() {
            display.asyncExec( new AsyncExecRunnable() );
          }
        };
        try {
          Fixture.runInThread( target );
        } catch( Throwable e ) {
          e.printStackTrace();
        }
      }
    } );
  }

  private void callDisplayWake() throws Throwable {
    Runnable runnable = new Runnable() {
      public void run() {
        display.wake();
      }
    };
    Fixture.runInThread( runnable );
  }

  private void fakeNewRequest() {
    Fixture.fakeNewRequest( display );
    ContextProvider.getSessionStore().setAttribute( "org.eclipse.swt.display", display );
  }

  private static ServiceContext createServiceContext( TestResponse response ) {
    HttpSession httpSession = ContextProvider.getContext().getSessionStore().getHttpSession();
    TestRequest request = new TestRequest();
    request.setSession( httpSession );
    ServiceContext result = new ServiceContext( request, response );
    result.setServiceStore( new ServiceStore() );
    return result;
  }

  private class AsyncExecRunnable implements Runnable {
    public void run() {
      log += RUN_ASYNC_EXEC;
    }
  }

  private class CallBackRequestSimulator {
    private final ServiceContext serviceContext;
    private volatile Thread requestThread;
    private volatile Throwable exception;

    CallBackRequestSimulator() {
      serviceContext = ContextProvider.getContext();
    }

    CallBackRequestSimulator( ServiceContext serviceContext ) {
      this.serviceContext = serviceContext;
    }

    void sendRequest() throws InterruptedException {
      requestThread = new Thread( new Runnable() {
        public void run() {
          ContextProvider.setContext( serviceContext );
          Fixture.fakeResponseWriter();
          try {
            manager.activateUICallBacksFor( "foo" );
            uiCallBackServiceHandler.service();
          } catch( Throwable thr ) {
            exception = thr;
          }
        }
      } );
      requestThread.start();
      Thread.sleep( SLEEP_TIME );
    }

    void waitForRequest() throws InterruptedException {
      requestThread.join();
    }

    boolean isRequestRunning() {
      return requestThread.isAlive();
    }

    boolean exceptionOccured() {
      return exception != null;
    }
  }
}
