/*****************************************************************************
 * © 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.List;

import javax.naming.InitialContext;

import com.avaya.collaboration.businessdata.api.NoAttributeFoundException;
import com.avaya.collaboration.businessdata.api.NoServiceProfileFoundException;
import com.avaya.collaboration.businessdata.api.NoUserFoundException;
import com.avaya.collaboration.businessdata.api.ServiceNotFoundException;

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

import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.CallPolicies;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.call.ParticipantFactory;
import com.avaya.collaboration.call.media.DigitOptions;
import com.avaya.collaboration.call.media.MediaFactory;
import com.avaya.collaboration.call.media.MediaServerInclusion;
import com.avaya.collaboration.call.media.MediaService;
import com.avaya.collaboration.call.media.PlayItem;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.platform.dal.api.ServiceDescriptor;
import com.avaya.zephyr.platform.dal.api.ServiceUtil;

@RunWith(PowerMockRunner.class)
@PrepareForTest(
{ MediaFactory.class, ServiceUtil.class, ParticipantFactory.class })
public class PromptAndCollectOperationImplTest
{
    private static final String TERM_KEY = "#";
    private static final int NUM_DIGITS = 1;
    private static final int TIMEOUT = DigitOptions.DEFAULT_TIMEOUT_MILLISECONDS;
    private static final boolean INTERRUPTIBLE = true;
    private static final String SRC_BGN = "://";
    private static final String SRC_END = "/services/Callingpolicies/Callingpolicies.wav";
    private final List<String> playListItems = new ArrayList<String>();
    @Mock
    private Call call;
    @Mock
    private Participant calledParty;
    @Mock
    private CallPolicies callPolicies;
    @Mock
    private DigitOptions digitOpts;
    @Mock
    private PlayItem playItm;
    @Mock
    private MediaService mediaSvc;
    @Mock
    private ServiceDescriptor svcDesc;
    @Mock
    private ClusterAttributeReader mClustrAttrRdr;
    @Mock
    private TrafficInterfaceAddressRetriever mTrafficIntfceAddrRtrvr;
    @Mock
    private ServiceAttributeReader mserviceAttributeReader;
    @Mock
    private SequentialForkingTimer noAnswerTimer;
    @Mock
    private InitialContext initialContext;
    @Mock
    private Logger logger;
    private PromptAndCollectOperation prmptNClctOper;

    @Before
    public void setUp() throws Exception
    {
        PowerMockito.mockStatic(MediaFactory.class);
        PowerMockito.mockStatic(ServiceUtil.class);
        PowerMockito.mockStatic(ParticipantFactory.class);

        when(call.getCallPolicies()).thenReturn(callPolicies);
        when(call.getCalledParty()).thenReturn(calledParty);
        when(ServiceUtil.getServiceDescriptor()).thenReturn(svcDesc);
        when(mClustrAttrRdr.getAnnouncementFileNetworkProtocol()).thenReturn("https");
        when(mTrafficIntfceAddrRtrvr.getTrafficInterfaceAddress()).thenReturn("10.129.177.214");
        when(digitOpts.getNumberOfDigits()).thenReturn(NUM_DIGITS);
        when(digitOpts.getTerminationKey()).thenReturn(TERM_KEY);
        when(digitOpts.getTimeout()).thenReturn(TIMEOUT);
        when(playItm.isInterruptible()).thenReturn(INTERRUPTIBLE);
        when(playItm.getIterateCount()).thenReturn(1);
        final String trafficInterfaceAddress = mTrafficIntfceAddrRtrvr.getTrafficInterfaceAddress();
        final String dfltProt = mClustrAttrRdr.getAnnouncementFileNetworkProtocol();
        final String source = dfltProt + SRC_BGN + trafficInterfaceAddress + SRC_END;
        playListItems.add(source);
        when(playItm.getSource()).thenReturn(playListItems);
        when(MediaFactory.createDigitOptions()).thenReturn(digitOpts);
        when(MediaFactory.createPlayItem()).thenReturn(playItm);
        when(MediaFactory.createMediaService()).thenReturn(mediaSvc);
        when(mserviceAttributeReader.getRedirectNumber(calledParty)).thenReturn("1234");
        when(mClustrAttrRdr.getDefaultClusterDomain()).thenReturn("ca.avaya.com");
        when(logger.isFinestEnabled()).thenReturn(true);
        when(logger.isFinerEnabled()).thenReturn(true);
        prmptNClctOper =
                new PromptAndCollectOperationImpl(mClustrAttrRdr, mTrafficIntfceAddrRtrvr,
                        mserviceAttributeReader, logger);
    }

    @Test
    public void executePromptAndCollectOperation_Success() throws Exception
    {
        prmptNClctOper.executePromptAndCollectOperation(call);

        verify(callPolicies).setMediaServerInclusion(MediaServerInclusion.AS_NEEDED);
    }
    
    @Test
    public void executePromptAndCollectOperation_Exception() throws Exception
    {
        final NoAttributeFoundException noAttr = new NoAttributeFoundException("No attribute found");
        doThrow(noAttr).when(mClustrAttrRdr).getAnnouncementFileNetworkProtocol();
        prmptNClctOper.executePromptAndCollectOperation(call);

        verify(callPolicies).setMediaServerInclusion(MediaServerInclusion.AS_NEEDED);
        verify(call).drop();
    }

    @Test
    public void cancelSequentialForkingTimer_noAnswerTimerIsNull()
    {
        prmptNClctOper.cancelSequentialForkingTimer(call);
        // verify(call, never()).setAttribute(CallingPoliciesMediaListener.OPTION_SELECTED, CallingPoliciesMediaListener.NO_SELECTION);
    }

    @Test
    public void cancelSequentialForkingTimer_noAnswerTimerExists_optionSelectedNotSeqFork() throws IllegalArgumentException, IllegalAccessException
    {
        MemberModifier.field(PromptAndCollectOperationImpl.class, "noAnswerTimer").set(prmptNClctOper, noAnswerTimer);
        when(call.getId()).thenReturn("test");
        CallingPoliciesMediaListener.callDigitSelectMap.put(call.getId(), CallingPoliciesMediaListener.ALLOW_DIGIT1);
        prmptNClctOper.cancelSequentialForkingTimer(call);
    }

    @Test
    public void cancelSequentialForkingTimer_noAnswerTimerExists_optionSelectedIsSeqFork() throws IllegalArgumentException, IllegalAccessException
    {
        MemberModifier.field(PromptAndCollectOperationImpl.class, "noAnswerTimer").set(prmptNClctOper, noAnswerTimer);
        when(call.getId()).thenReturn("test");
        CallingPoliciesMediaListener.callDigitSelectMap.put(call.getId(), CallingPoliciesMediaListener.SEQUENTIALFORK_DIGIT5);
        prmptNClctOper.cancelSequentialForkingTimer(call);
    }

    @Test
    public void startNoAnswerTimer_noAnswerTimerIsNull()
    {
        prmptNClctOper.startNoAnswerTimer(call);
        verify(noAnswerTimer, never()).createTimer(Matchers.anyLong(), Matchers.anyString());
    }

    @Test
    public void startNoAnswerTimer_noAnswerTimerExists() throws IllegalArgumentException, IllegalAccessException
    {
        MemberModifier.field(PromptAndCollectOperationImpl.class, "noAnswerTimer").set(prmptNClctOper, noAnswerTimer);
        when(call.getUCID()).thenReturn("callID");
        prmptNClctOper.startNoAnswerTimer(call);
        verify(noAnswerTimer).createTimer(10000L, "callID");
    }

    @Test
    public void addPartyToCall_noDomain() throws NoAttributeFoundException
    {
        final String defaultDmn = mClustrAttrRdr.getDefaultClusterDomain();
        when(ParticipantFactory.create("1234", defaultDmn)).thenReturn(calledParty);
        prmptNClctOper.addPartyToCall(call);

        verify(call).addParticipant(calledParty);
    }

    @Test
    public void addPartyToCall_noDomain_logDisabled() throws NoAttributeFoundException
    {
        final String defaultDmn = mClustrAttrRdr.getDefaultClusterDomain();
        when(ParticipantFactory.create("1234", defaultDmn)).thenReturn(calledParty);
        when(logger.isFinerEnabled()).thenReturn(false);
        prmptNClctOper.addPartyToCall(call);

        verify(call).addParticipant(calledParty);
    }

    @Test
    public void addPartyToCall_DomainExists() throws NoAttributeFoundException, NoUserFoundException, ServiceNotFoundException,
            NoServiceProfileFoundException
    {
        when(mserviceAttributeReader.getRedirectNumber(calledParty)).thenReturn("1234@avaya.com");
        when(ParticipantFactory.create("1234", "avaya.com", "Adding New Party ...1234")).thenReturn(calledParty);
        prmptNClctOper.addPartyToCall(call);

        verify(call).addParticipant(calledParty);
    }

    @Test
    public void addPartyToCall_exception()
    {
        final NullPointerException npe = new NullPointerException();
        doThrow(npe).when(call).addParticipant(Matchers.any(Participant.class));
        prmptNClctOper.addPartyToCall(call);

        verify(call).drop();
    }
}
