package com.avaya.zephyr.services.sample_services.CallableService.menus;

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

import java.util.UUID;

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

import com.avaya.collaboration.businessdata.api.ServiceData;
import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.call.media.DigitCollectorOperationCause;
import com.avaya.collaboration.call.media.MediaFactory;
import com.avaya.collaboration.call.media.MediaService;
import com.avaya.collaboration.call.media.PlayItem;
import com.avaya.collaboration.call.media.PlayOperationCause;
import com.avaya.collaboration.call.media.RecordOperationCause;
import com.avaya.collaboration.dal.factory.CollaborationDataFactory;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.platform.dal.api.ServiceDescriptor;
import com.avaya.zephyr.platform.dal.api.ServiceUtil;
import com.avaya.zephyr.services.sample_services.CallableService.PromptsToPlay;
import com.avaya.zephyr.services.sample_services.CallableService.attributeReaders.ServiceAttributeReaderImpl;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PlayAnnouncementOperationImpl;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PromptAndCollectOperation;
import com.avaya.zephyr.services.sample_services.CallableService.operations.RecordMessageOperation;
import com.avaya.zephyr.services.sample_services.CallableService.util.CallableServiceHttpUtil;

@RunWith(PowerMockRunner.class)
@PrepareForTest(
{ CallableServiceMainMenuMediaListener.class, MediaFactory.class, CallableServiceHttpUtil.class, PlayAnnouncementOperationImpl.class,
        ServiceAttributeReaderImpl.class, ServiceUtil.class, ServiceDescriptor.class,
        CollaborationDataFactory.class })
public class CallableServiceMainMenuMediaListenerTest
{

    CallableServiceMainMenuMediaListener callableServiceMainMenuMediaListener;
    DigitCollectorOperationCause DIGIT_CAUSE = DigitCollectorOperationCause.NUMBER_OF_DIGITS;
    RecordOperationCause RECORD_CAUSE = RecordOperationCause.TERMINATION_KEY_PRESSED;
    PlayOperationCause PLAY_CAUSE = PlayOperationCause.COMPLETE;
    @Mock
    CallableServiceHttpUtil callableServiceHttpUtil;
    @Mock
    PlayAnnouncementOperationImpl playAnnouncementOperationImpl;
    @Mock
    PromptAndCollectOperation promptAndCollectOperation; 
    @Mock
    RecordMessageOperation recordMessageOperation;
    @Mock
    ServiceAttributeReaderImpl serviceAttributeReaderImpl;
    @Mock
    PlayItem playItem;
    @Mock
    MediaService mediaService;
    @Mock
    Call call;
    @Mock
    Logger logger;
    @Mock
    ServiceDescriptor serviceDescriptor;
    @Mock
    Participant participant;
    @Mock
    ServiceData serviceData;

    @Before
    public void setUp() throws Exception
    {
        PowerMockito.mockStatic(MediaFactory.class);
        BDDMockito.given(MediaFactory.createPlayItem()).willReturn(playItem);
        BDDMockito.given(MediaFactory.createMediaService()).willReturn(mediaService);
        PowerMockito.mockStatic(ServiceUtil.class);
        BDDMockito.given(ServiceUtil.getServiceDescriptor()).willReturn(serviceDescriptor);
        
        when(serviceDescriptor.getName()).thenReturn("CallableService");
        when(serviceDescriptor.getVersion()).thenReturn("1.0.0.0");
        when(call.getCalledParty()).thenReturn(participant);
        when(call.getCallingParty()).thenReturn(participant);
        when(participant.getHandle()).thenReturn("1234");
        when(call.wasServiceCalled()).thenReturn(true);
        PowerMockito.mockStatic(CollaborationDataFactory.class);
        PowerMockito.mockStatic(ServiceAttributeReaderImpl.class);
        PowerMockito.mockStatic(CallableServiceHttpUtil.class);
        PowerMockito.whenNew(ServiceAttributeReaderImpl.class).withAnyArguments().thenReturn(serviceAttributeReaderImpl);
        PowerMockito.whenNew(CallableServiceHttpUtil.class).withAnyArguments().thenReturn(callableServiceHttpUtil);
        when(serviceAttributeReaderImpl.getFileName(Mockito.any(Participant.class))).thenReturn("testName");
        callableServiceMainMenuMediaListener = new CallableServiceMainMenuMediaListener(call, playAnnouncementOperationImpl,
        		promptAndCollectOperation, recordMessageOperation, logger);
    }

    @Test
    public void digitsCollected_record()
    {
    	when(logger.isFinerEnabled()).thenReturn(true);
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "1", DIGIT_CAUSE);
        verify(playAnnouncementOperationImpl, Mockito.times(1)).executePlayAnnouncementOperation(call, PromptsToPlay.RECORD);
    }

    @Test
    public void digitsCollected_play_prev_recorded_does_not_exist()
    {
    	when(callableServiceHttpUtil.requestPut(Mockito.anyString())).thenReturn("DOES NOT EXIST");
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "2", DIGIT_CAUSE);
        verify(playAnnouncementOperationImpl, Mockito.never()).executePlayAnnouncementOperation(Mockito.any(Call.class), Mockito.anyString());
    }
    
    @Test
    public void digitsCollected_play_prev_recorded_exists()
    {
    	when(callableServiceHttpUtil.requestPut(Mockito.anyString())).thenReturn("EXISTS");
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "2", DIGIT_CAUSE);
        verify(playAnnouncementOperationImpl, Mockito.times(1)).executePlayAnnouncementOperation(Mockito.any(Call.class), Mockito.anyString());
    }

    @Test
    public void digitsCollected_del_prev_recorded_http_ok()
    {
    	
    	when(logger.isFinestEnabled()).thenReturn(true);
    	when(callableServiceHttpUtil.requestDelete(Mockito.anyString())).thenReturn(200);
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "3", DIGIT_CAUSE);
        verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.THANKYOU);
    }
    
    @Test
    public void digitsCollected_del_prev_recorded_failed()
    {
    	when(logger.isFinestEnabled()).thenReturn(false);
    	when(callableServiceHttpUtil.requestDelete(Mockito.anyString())).thenReturn(1);
    	callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "3", DIGIT_CAUSE);
    	verify(call, Mockito.never()).setAttribute("nextPrompt", PromptsToPlay.THANKYOU);
    }
    
    @Test
    public void digitsCollected_invalid_digit()
    {
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "9", DIGIT_CAUSE);
        verify(logger, Mockito.times(1)).error(Mockito.any());
    }
    
    @Test
    public void digitsCollected_exit_app()
    {
        callableServiceMainMenuMediaListener.digitsCollected(UUID.randomUUID(), "*", DIGIT_CAUSE);
        verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.THANKYOU);
    }
    
    @Test
    public void recordCompleted()
    {
    	when(logger.isFinestEnabled()).thenReturn(true);
    	callableServiceMainMenuMediaListener.recordCompleted(UUID.randomUUID(), RECORD_CAUSE);
    	verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.RECORDING_SAVED);
    }
    
    @Test
    public void playCompleted_MainMenu()
    {
    	when(logger.isFinestEnabled()).thenReturn(true);
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.MAINMENU);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(promptAndCollectOperation, Mockito.times(1)).executePromptAndCollectOperation(call, PromptsToPlay.MAINMENU);
    }
    
    @Test
    public void playCompleted_Record()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.RECORD);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(recordMessageOperation, Mockito.times(1)).executeRecordMessageOperation(call);
    }
    
    @Test
    public void playCompleted_Beep()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.BEEP);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
        verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.RECORD);
    }
    
    @Test
    public void playCompleted_ApproveOrDiscard()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.APPROVE_OR_DISCARD);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.RECORDING_SAVED);
    }
    
    @Test
    public void playCompleted_RecordingSaved()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.RECORDING_SAVED);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
        verify(logger, Mockito.never()).error(Mockito.any());
    }
    @Test
    public void playCompleted_ReturnToMainMenu()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.RETURN_TO_MAINMENU);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(call, Mockito.times(1)).setAttribute("nextPrompt", PromptsToPlay.MAINMENU);
    }
    @Test
    public void playCompleted_ThankYou()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.THANKYOU);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(call, Mockito.times(1)).drop();
    }
    @Test
    public void playCompleted_InvalidPrompt()
    {
    	when(call.getAttribute("nextPrompt")).thenReturn(PromptsToPlay.GREETING);
    	callableServiceMainMenuMediaListener.playCompleted(UUID.randomUUID(), PLAY_CAUSE);
    	verify(logger, Mockito.times(1)).error(Mockito.any());
    }
}
