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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
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.businessdata.api.NoAttributeFoundException;
import com.avaya.collaboration.businessdata.api.ServiceData;
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 ServiceAttributeReaderImplTest
{
    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 RDR_NUM = "3405@avaya.com";
    private static final String RDR_NO_DMN = "3405";
    @Mock
    private ServiceDescriptor svcDesc;
    @Mock
    private ServiceData svcData;
    @Mock
    private ServiceAttributeReader mSvcAttrRdr;
    @Mock
    private Call call;
    @Mock
    private Participant caller, called;
    private ServiceAttributeReader svcAttrRdr;

    @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(ServiceUtil.getServiceDescriptor()).thenReturn(svcDesc);
        final String svcDescName = svcDesc.getName();
        final String svcDescVersion = svcDesc.getVersion();
        when(CollaborationDataFactory.getServiceData(svcDescName, svcDescVersion)).thenReturn(svcData);
        svcAttrRdr = new ServiceAttributeReaderImpl(svcDesc);
    }

    @Test
    public void getForkedDestinations_forks() 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(mSvcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject())).thenReturn(forkDest);
        final List<String> mSvcAttrRdrForkDest = new ArrayList<String>();
        mSvcAttrRdrForkDest.addAll(mSvcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject()));
        final List<String> svcAttrRdrForkDest = new ArrayList<String>();
        svcAttrRdrForkDest.addAll(svcAttrRdr.getForkedDestinations((Participant) called));

        assertEquals(mSvcAttrRdrForkDest, svcAttrRdrForkDest);
        assertEquals(mSvcAttrRdrForkDest.get(0), svcAttrRdrForkDest.get(0));
        assertEquals(mSvcAttrRdrForkDest.get(1), svcAttrRdrForkDest.get(1));
    }

    @Test
    public void getForkedDestinations_forks_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(mSvcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject())).thenReturn(forkDest);
        final List<String> mSvcAttrRdrForkDest = new ArrayList<String>();
        mSvcAttrRdrForkDest.addAll(mSvcAttrRdr.getForkedDestinations((Participant) Matchers.anyObject()));
        final List<String> svcAttrRdrForkDest = new ArrayList<String>();
        svcAttrRdrForkDest.addAll(svcAttrRdr.getForkedDestinations((Participant) called));

        assertEquals(mSvcAttrRdrForkDest, svcAttrRdrForkDest);
        assertEquals(mSvcAttrRdrForkDest.get(0), svcAttrRdrForkDest.get(0));
        assertEquals(mSvcAttrRdrForkDest.get(1), svcAttrRdrForkDest.get(1));
    }

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

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

    @Test
    public void getRedirectNumber_redirectNumber() throws Exception
    {
        when(svcData.getServiceAttribute(Matchers.anyString(), Matchers.anyString())).thenReturn(RDR_NUM);
        when(mSvcAttrRdr.getRedirectNumber((Participant) Matchers.anyObject())).thenReturn(RDR_NUM);
        final String mRdrNum = mSvcAttrRdr.getRedirectNumber((Participant) Matchers.anyObject());
        final String actualRdrNum = svcAttrRdr.getRedirectNumber((Participant) called);

        assertEquals(mRdrNum, actualRdrNum);
    }

    @Test
    public void getRedirectNumber_redirectNumber_no_domain() throws Exception
    {
        when(svcData.getServiceAttribute(Matchers.anyString(), Matchers.anyString())).thenReturn(RDR_NO_DMN);
        when(mSvcAttrRdr.getRedirectNumber((Participant) Matchers.anyObject())).thenReturn(RDR_NO_DMN);
        final String mRdrNum = mSvcAttrRdr.getRedirectNumber((Participant) Matchers.anyObject());
        final String actualRdrNum = svcAttrRdr.getRedirectNumber((Participant) called);

        assertEquals(mRdrNum, actualRdrNum);
    }

    @Test(expected = NoAttributeFoundException.class)
    public void getRedirectNumber_invalidRedirectNumber() throws Exception
    {
        final NoAttributeFoundException noAttr = new NoAttributeFoundException("no redirect Number");
        doThrow(noAttr).when(svcData).getServiceAttribute(Matchers.anyString(), Matchers.anyString());
        doThrow(noAttr).when(mSvcAttrRdr).getRedirectNumber((Participant) Matchers.anyObject());

        fail(svcAttrRdr.getRedirectNumber((Participant) called));
    }
}
