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

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
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.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.avaya.collaboration.businessdata.api.NoAttributeFoundException;
import com.avaya.collaboration.businessdata.api.ServiceData;
import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.call.ParticipantFactory;
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;

@RunWith(PowerMockRunner.class)
@PrepareForTest(
{ CollaborationDataFactory.class, ServiceUtil.class, ParticipantFactory.class })
public class ForkingOperationImplTest
{
    private static final String DOMAIN = "avaya.com";
    private static final String CALLER = "3404@avaya.com";
    private static final String CALLED = "3403@avaya.com";
    private static final String CALLER_NO_DOMAIN = "3404";
    private static final String CALLED_NO_DOMAIN = "3403";
    private static final String CALLER_DISPLAY = "Trying Fork...3404";
    private static final String CALLED_DISPLAY = "Trying Fork...3403";
    private static final String LOG__BEGIN = "toFork:  CalledParty=";
    private static final String LOG_END = "forkingOperation  Forks=";
    @Mock
    private ServiceDescriptor svcDesc;
    @Mock
    private ServiceData svcData;
    @Mock
    private ServiceAttributeReader svcAttrRdr;
    @Mock
    private ClusterAttributeReader clustrAttrRdr;
    @Mock
    private Call call;
    @Mock
    private Participant caller, called;
    @Mock
    private Logger logger;
    private ForkingOperation forkOperation;

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

        when(caller.getHandle()).thenReturn(CALLER_NO_DOMAIN);
        when(caller.getDomain()).thenReturn(DOMAIN);
        when(caller.getAddress()).thenReturn(CALLER);
        when(called.getHandle()).thenReturn(CALLED_NO_DOMAIN);
        when(called.getDomain()).thenReturn(DOMAIN);
        when(called.getAddress()).thenReturn(CALLED);
        when(call.getCallingParty()).thenReturn(caller);
        when(call.getCalledParty()).thenReturn(called);
        when(logger.isFinestEnabled()).thenReturn(true);
        when(ServiceUtil.getServiceDescriptor()).thenReturn(svcDesc);
        final String svcDescName = svcDesc.getName();
        final String svcDescVersion = svcDesc.getVersion();
        when(CollaborationDataFactory.getServiceData(svcDescName, svcDescVersion)).thenReturn(svcData);
        forkOperation = new ForkingOperationImpl(svcAttrRdr, clustrAttrRdr, logger);
    }

    @Test
    public void forkTo_fork() throws Exception
    {
        final List<String> forkDest = new ArrayList<String>();
        when(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute")).thenReturn(CALLER);
        when(svcData.getServiceAttribute(Matchers.anyString(), Matchers.anyString())).thenReturn(CALLER);
        when(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute")).thenReturn(CALLED);
        forkDest.add(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute"));
        forkDest.add(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute"));
        when(svcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject())).thenReturn(forkDest);
        when(ParticipantFactory.create(CALLER_NO_DOMAIN, DOMAIN, CALLER_DISPLAY)).thenReturn(caller);
        when(ParticipantFactory.create(CALLED_NO_DOMAIN, DOMAIN, CALLED_DISPLAY)).thenReturn(called);
        forkOperation.forkTo(call);

        verify(logger).finest(LOG__BEGIN + call.getCalledParty() + LOG_END + forkDest);
        verify(call).addParticipant(caller);
        verify(call).addParticipant(called);
    }

    @Test
    public void forkTo_fork_no_domain() throws Exception
    {
        final List<String> forkDest = new ArrayList<String>();
        when(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute")).thenReturn(CALLER_NO_DOMAIN);
        when(svcData.getServiceAttribute(Matchers.anyString(), Matchers.anyString())).thenReturn(
                CALLER_NO_DOMAIN);
        when(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute")).thenReturn(CALLED_NO_DOMAIN);
        forkDest.add(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute"));
        forkDest.add(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute"));
        when(svcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject())).thenReturn(forkDest);
        final String defaultDmn = clustrAttrRdr.getDefaultClusterDomain();
        when(ParticipantFactory.create(CALLER_NO_DOMAIN, defaultDmn)).thenReturn(caller);
        when(ParticipantFactory.create(CALLED_NO_DOMAIN, defaultDmn)).thenReturn(called);
        forkOperation.forkTo(call);

        verify(logger).finest(LOG__BEGIN + call.getCalledParty() + LOG_END + forkDest);
        verify(call).addParticipant(caller);
        verify(call).addParticipant(called);
    }

    @Test(expected = NoAttributeFoundException.class)
    public void forkTo_invalidForks() throws Exception
    {
        final List<String> forkDest = new ArrayList<String>();
        when(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute")).thenReturn(" ");
        when(svcData.getServiceAttribute(Matchers.anyString(), Matchers.anyString())).thenReturn(" ");
        when(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute")).thenReturn(" ");
        forkDest.add(svcData.getServiceAttribute(CALLER, "forkDestination1Attribute"));
        forkDest.add(svcData.getServiceAttribute(CALLED, "forkDestination2Attribute"));
        final NoAttributeFoundException noAttr = new NoAttributeFoundException("no fork");
        doThrow(noAttr).when(svcAttrRdr).getForkedDestinations((Participant) Matchers.anyObject());

        assertTrue((svcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject())) instanceof NoAttributeFoundException);
    }
}
