package com.avaya.zephyr.services.dynamicteamformation;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.expectLastCall;
import static org.powermock.api.easymock.PowerMock.expectNew;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.api.easymock.PowerMock.replayAll;
import static org.powermock.api.easymock.PowerMock.verifyAll;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.avaya.collaboration.businessdata.api.ServiceData;
import com.avaya.collaboration.conference.scheduled.SchedConf;
import com.avaya.collaboration.conference.scheduled.SchedConfFactory;
import com.avaya.collaboration.dal.factory.CollaborationDataFactory;
import com.avaya.collaboration.email.EmailFactory;
import com.avaya.collaboration.sms.SmsFactory;
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.dynamicteamformation.conference.DynamicTeamFormationConferenceScheduler;
import com.avaya.zephyr.services.dynamicteamformation.email.DynamicTeamFormationEmailListener;
import com.avaya.zephyr.services.dynamicteamformation.email.DynamicTeamFormationEmailSender;
import com.avaya.zephyr.services.dynamicteamformation.sms.DynamicTeamFormationSmsListener;
import com.avaya.zephyr.services.dynamicteamformation.sms.DynamicTeamFormationSmsSender;

@RunWith(PowerMockRunner.class)
@PrepareForTest(
{ EmailFactory.class, SmsFactory.class, ServiceUtil.class,
        CollaborationDataFactory.class, SchedConfFactory.class,
        DynamicTeamFormationSmsListener.class, DynamicTeamFormationEmailListener.class,
        DynamicTeamFormationServlet.class })
public final class DynamicTeamFormationServletTest
{
    private DynamicTeamFormationServlet dynamicTeamFormationServletTest;
    private Logger mockLogger;
    private PrintWriter mockPrinterWriter;
    private HttpServletRequest mockHttpServletRequest;
    private HttpServletResponse mockHttpServletResponse;
    private ServiceDescriptor mockServiceDescriptor;
    private ServiceData mockServiceData;
    private DynamicTeamFormationConferenceScheduler mockDynamicTeamFormationConferenceScheduler;
    private DynamicTeamFormationEmailSender mockDynamicTeamFormationEmailSender;
    private DynamicTeamFormationSmsSender mockDynamicTeamFormationSmsSender;

    private SchedConf mockSchedConf;

    @Before
    public void setUpMockCommon() throws Exception
    {
        mockLogger = createMock(Logger.class);
        mockPrinterWriter = createMock(PrintWriter.class);
        mockHttpServletRequest = createMock(HttpServletRequest.class);
        mockHttpServletResponse =
                createMock(HttpServletResponse.class);
        mockServiceDescriptor = createMock(ServiceDescriptor.class);
        mockServiceData = createMock(ServiceData.class);
        mockSchedConf = createMock(SchedConf.class);
        mockDynamicTeamFormationConferenceScheduler =
                createMock(DynamicTeamFormationConferenceScheduler.class);
        mockDynamicTeamFormationEmailSender =
                createMock(DynamicTeamFormationEmailSender.class);
        mockDynamicTeamFormationSmsSender =
                createMock(DynamicTeamFormationSmsSender.class);

        dynamicTeamFormationServletTest = new DynamicTeamFormationServlet(mockLogger);

        expect(mockHttpServletResponse.getWriter()).andReturn(mockPrinterWriter);
        mockLogger.info("doPost");
        expectLastCall();
        mockHttpServletResponse.setContentType("text/plain");
        expectLastCall();
    }

    private void setUpMockServiceData() throws Exception
    {
        mockStatic(ServiceUtil.class);
        expect(ServiceUtil.getServiceDescriptor()).andReturn(mockServiceDescriptor);
        mockStatic(CollaborationDataFactory.class);
        expect(CollaborationDataFactory.getServiceData(mockServiceDescriptor.getName(),
                mockServiceDescriptor.getVersion())).andReturn(mockServiceData);
    }

    private void setUpMockServiceDataNull() throws Exception
    {
        mockStatic(ServiceUtil.class);
        expect(ServiceUtil.getServiceDescriptor()).andReturn(null);
        mockLogger.error((String) anyObject());
        expectLastCall();
        mockPrinterWriter.println((String) anyObject());
        mockHttpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        expectLastCall();
    }

    private void setupMockConferenceScheduler() throws Exception
    {
        expectNew(DynamicTeamFormationConferenceScheduler.class, mockServiceData, mockHttpServletRequest,
                mockPrinterWriter)
                .andReturn(mockDynamicTeamFormationConferenceScheduler);
        expect(mockDynamicTeamFormationConferenceScheduler.scheduleConference()).andReturn(mockSchedConf);
    }

    private void setupMockConferenceSchedulerException() throws Exception
    {
        expectNew(DynamicTeamFormationConferenceScheduler.class, mockServiceData, mockHttpServletRequest,
                mockPrinterWriter)
                .andReturn(mockDynamicTeamFormationConferenceScheduler);
        Exception mockException = createMock(Exception.class);
        expect(mockDynamicTeamFormationConferenceScheduler.scheduleConference()).andThrow(mockException);
        mockLogger.error("Error: Error scheduling the conference.", mockException);
        expectLastCall();
        mockPrinterWriter.println((String) anyObject());
        mockHttpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }

    private void setupMockEmailSender(boolean sent) throws Exception
    {
        expectNew(DynamicTeamFormationEmailSender.class, mockServiceData, mockHttpServletRequest,
                mockPrinterWriter)
                .andReturn(mockDynamicTeamFormationEmailSender);
        expect(mockDynamicTeamFormationEmailSender.sendEmail(mockSchedConf)).andReturn(sent);
    }

    private void setupMockSmsSender(boolean sent) throws Exception
    {
        expectNew(DynamicTeamFormationSmsSender.class, mockServiceData, mockHttpServletRequest,
                mockPrinterWriter)
                .andReturn(mockDynamicTeamFormationSmsSender);
        expect(mockDynamicTeamFormationSmsSender.sendSms(mockSchedConf)).andReturn(sent);
    }

    @Test
    public void testServiceDataNull() throws Exception
    {
        // Test Info

        // Test Data

        // Setup mocks
        setUpMockServiceDataNull();

        // Replay, Execute, and Verify
        replayAll();
        dynamicTeamFormationServletTest.doPost(mockHttpServletRequest, mockHttpServletResponse);
        verifyAll();
    }

    @Test
    public void testScheduleConferenceException() throws Exception
    {
        // Test Info

        // Test Data

        // Setup mocks
        setUpMockServiceData();
        setupMockConferenceSchedulerException();

        // Replay, Execute, and Verify
        replayAll();
        dynamicTeamFormationServletTest.doPost(mockHttpServletRequest, mockHttpServletResponse);
        verifyAll();
    }

    @Test
    public void testNoEmailSms() throws Exception
    {
        // Test Info

        // Test Data

        // Setup mocks
        setUpMockServiceData();
        setupMockConferenceScheduler();
        setupMockEmailSender(false);
        setupMockSmsSender(false);
        mockHttpServletResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        expectLastCall();

        // Replay, Execute, and Verify
        replayAll();
        dynamicTeamFormationServletTest.doPost(mockHttpServletRequest, mockHttpServletResponse);
        verifyAll();
    }

    @Test
    public void testEmailSend() throws Exception
    {
        // Test Info

        // Test Data

        // Setup mocks
        setUpMockServiceData();
        setupMockConferenceScheduler();
        setupMockEmailSender(true);
        setupMockSmsSender(false);
        mockHttpServletResponse.setStatus(HttpServletResponse.SC_OK);
        expectLastCall();

        // Replay, Execute, and Verify
        replayAll();
        dynamicTeamFormationServletTest.doPost(mockHttpServletRequest, mockHttpServletResponse);
        verifyAll();
    }

    @Test
    public void testSmsSend() throws Exception
    {
        // Test Info

        // Test Data

        // Setup mocks
        setUpMockServiceData();
        setupMockConferenceScheduler();
        setupMockEmailSender(false);
        setupMockSmsSender(true);
        mockHttpServletResponse.setStatus(HttpServletResponse.SC_OK);
        expectLastCall();

        // Replay, Execute, and Verify
        replayAll();
        dynamicTeamFormationServletTest.doPost(mockHttpServletRequest, mockHttpServletResponse);
        verifyAll();
    }
}