/*****************************************************************************
 * © 2015 Avaya Inc. All rights reserved.
 ****************************************************************************/
package com.avaya.services.Callingpolicies;

import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Collection;

import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.CallFactory;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.util.logger.Logger;

@RunWith(PowerMockRunner.class)
@PrepareForTest(
{ CallFactory.class })
public class SequentialForkingTimerTest
{
    @Mock
    private TimerService timerServiceMock;
    @Mock
    private Timer timerMock;
    @Mock
    private Logger loggerMock;
    @Mock
    private Call callMock;
    @Mock
    private Participant calledPartyMock;

    private Collection<Timer> timers = new ArrayList<Timer>();

    private SequentialForkingTimer sequentialForkingTimer;

    private static final String testCall = "test_call";
    private static final String differentTestCall = "different_test_call";

    @Before
    public void setUp()
    {
        PowerMockito.mockStatic(CallFactory.class);
        sequentialForkingTimer = new SequentialForkingTimer(timerServiceMock, loggerMock);
        when(loggerMock.isInfoEnabled()).thenReturn(true);
        when(loggerMock.isFineEnabled()).thenReturn(true);
        when(loggerMock.isFinerEnabled()).thenReturn(true);
        when(loggerMock.isFinestEnabled()).thenReturn(true);
        when(timerServiceMock.createSingleActionTimer(Mockito.eq(10000L), Mockito.any(TimerConfig.class))).thenReturn(timerMock);
        timers.add(timerMock);
    }

    @Test
    public void init_noTimersExisted()
    {
        when(timerServiceMock.getTimers()).thenReturn(null);
        sequentialForkingTimer.init();
        verify(timerMock, never()).cancel();
    }

    @Test
    public void init_timersExisted()
    {
        when(timerServiceMock.getTimers()).thenReturn(timers);
        sequentialForkingTimer.init();
        verify(timerMock).cancel();
    }

    @Test
    public void init_exception()
    {
        when(timerServiceMock.getTimers()).thenReturn(timers);
        final NullPointerException e = new NullPointerException();
        doThrow(e).when(timerMock).cancel();
        sequentialForkingTimer.init();
        verify(timerMock).cancel();
    }

    @Test
    public void createTimer()
    {
        when(timerServiceMock.createSingleActionTimer(Mockito.eq(10000L), Mockito.any(TimerConfig.class))).thenReturn(timerMock);
        sequentialForkingTimer.createTimer(10000L, testCall);
        verify(timerServiceMock).createSingleActionTimer(Mockito.eq(10000L), Mockito.any(TimerConfig.class));
    }

    @Test
    public void cancelTimer_success()
    {
        when(timerServiceMock.getTimers()).thenReturn(timers);
        when(timerMock.getInfo()).thenReturn(testCall);
        sequentialForkingTimer.cancelTimer(testCall);
        verify(timerMock).cancel();
    }

    @Test
    public void cancelTimer_wrong_callId()
    {
        when(timerServiceMock.getTimers()).thenReturn(timers);
        when(timerMock.getInfo()).thenReturn(differentTestCall);
        sequentialForkingTimer.cancelTimer(testCall);
        verify(timerMock, never()).cancel();
    }

    @Test
    public void cancelTimer_exception()
    {
        when(timerServiceMock.getTimers()).thenReturn(timers);
        final NullPointerException e = new NullPointerException();
        when(timerMock.getInfo()).thenThrow(e);
        sequentialForkingTimer.cancelTimer("testCall");
        verify(loggerMock).finest("init: timer was not cancelled properly", e);
    }

    @Test
    public void onTimer()
    {
        when(timerMock.getInfo()).thenReturn(testCall);
        when(CallFactory.getCall(testCall)).thenReturn(callMock);
        when(callMock.getCalledParty()).thenReturn(calledPartyMock);
        sequentialForkingTimer.onTimer(timerMock);
        verify(callMock).dropParticipant(calledPartyMock);
    }
}

