/****************************************************************************
 * Copyright Avaya Inc., All Rights Reserved.
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Avaya Inc.
 * The copyright notice above does not evidence any actual or intended publication of such source code.
 * Some third-party source code components may have been modified from their original versions by Avaya Inc.
 * The modifications are Copyright Avaya Inc., All Rights Reserved.
 * Avaya Confidential & Restricted. May not be distributed further without written permission of
 * the Avaya owner.
 ****************************************************************************/
package com.avaya.zephyr.services.sample_services.Authorization.TaskDashboard;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import com.avaya.collaboration.authorization.AuthorizationHelperException;
import com.avaya.collaboration.authorization.client.AccessToken;
import com.avaya.collaboration.authorization.client.AuthorizationClientHelper;
import com.avaya.collaboration.authorization.client.HttpResponseException;
import com.avaya.collaboration.authorization.spi.AccessTokenProvider;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.common.logging.client.LogLevel;
import com.avaya.zephyr.common.testutils.deencapsulation.Deencapsulation;
import com.avaya.zephyr.services.TaskDashboard.types.ResopnseJson;
import com.avaya.zephyr.services.TaskDashboard.types.Task;
import com.avaya.zephyr.services.sample_services.Authorization.TaskDashboard.provider.EndpointProvider;
import com.avaya.zephyr.services.sample_services.Authorization.TaskDashboard.provider.HttpUtilProvider;
import com.google.gson.Gson;

@RunWith(MockitoJUnitRunner.class)
public class TaskDashboardTest
{
    TaskDashboard sampleClientResource;
    @Mock
    AccessTokenProvider mockAccessTokenProvider;
    @Mock
    AccessToken mockAccessToken;
    @Mock
    HttpUtilProvider mockHttpUtilProvider;
    @Mock
    HttpGet mockHttpGet;
    @Mock
    CloseableHttpClient mockCloseableHttpClient;
    @Mock
    CloseableHttpResponse mockCloseableHttpResponse;
    @Mock
    Logger mockLogger;
    @Mock
    private EndpointProvider provider;
    @Mock
    HttpResponse mockHttpResponse;
    @Mock
    StatusLine statusLine;
    @Mock
    HttpServletRequest httpServletRequest;

    @Before
    public void before()
    {
        Logger.getLogger(TaskDashboard.class).setLevel(LogLevel.FINEST);
        sampleClientResource = new TaskDashboard(mockHttpUtilProvider, mockLogger, provider);
        Deencapsulation.setField(AuthorizationClientHelper.class, "tokenProvider", mockAccessTokenProvider);
    }

    @Test
    public void getResource_resourceRequest_success() throws Exception
    {
        when(mockAccessTokenProvider.getAccessToken(Arrays.asList("listall"))).thenReturn(mockAccessToken);
        when(mockHttpUtilProvider.getHttpClient()).thenReturn(mockCloseableHttpClient);
        try
        {
            when(mockCloseableHttpClient.execute(Mockito.isA(HttpGet.class))).thenReturn(mockCloseableHttpResponse);

        }
        catch (ClientProtocolException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        when(mockCloseableHttpResponse.getStatusLine()).thenReturn(statusLine);
        when(statusLine.getStatusCode()).thenReturn(200);

        Gson gson = new Gson();
        ResopnseJson responseJson = new ResopnseJson();
        Task task = new Task();
        task.setId("1");
        task.setTitle("test");
        List<Task> tasks = new ArrayList<Task>();
        tasks.add(task);
        responseJson.setTasks(tasks);
        String json = gson.toJson(responseJson);
        when(mockHttpUtilProvider.getHttpResponseAsString(mockCloseableHttpResponse)).thenReturn(json);
        when(provider.getResourceEndpoint()).thenReturn("https://localhost");
        
        Response response = sampleClientResource.getResource();
        
        assertEquals(200, response.getStatus());
    }

    @Test
    public void getResource_resourceRequest_emptyUrl() throws Exception
    {
        Response response = sampleClientResource.getResource();
        
        assertEquals(500, response.getStatus());
    }

    @Test
    public void getResource_resourceRequest_nullToken() throws Exception
    {
        when(provider.getResourceEndpoint()).thenReturn("https://localhost");
        
        Response response = sampleClientResource.getResource();
        
        assertEquals(500, response.getStatus());
    }

    @Test
    public void getResource_resourceRequest_ststus500() throws Exception
    {
        when(mockAccessTokenProvider.getAccessToken(Arrays.asList("listall"))).thenReturn(mockAccessToken);
        when(mockHttpUtilProvider.getHttpClient()).thenReturn(mockCloseableHttpClient);
        try
        {
            when(mockCloseableHttpClient.execute(Mockito.isA(HttpGet.class))).thenReturn(mockCloseableHttpResponse);

        }
        catch (ClientProtocolException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        when(mockCloseableHttpResponse.getStatusLine()).thenReturn(statusLine);
        when(statusLine.getStatusCode()).thenReturn(500);
        Gson gson = new Gson();
        ResopnseJson responseJson = new ResopnseJson();
        Task task = new Task();
        task.setId("1");
        task.setTitle("test");
        List<Task> tasks = new ArrayList<Task>();
        tasks.add(task);
        responseJson.setTasks(tasks);
        String json = gson.toJson(responseJson);
        when(mockHttpUtilProvider.getHttpResponseAsString(mockCloseableHttpResponse)).thenReturn(json);
        when(provider.getResourceEndpoint()).thenReturn("https://localhost");
        
        Response response = sampleClientResource.getResource();
        
        assertEquals(500, response.getStatus());
    }

    @Test
    public void getResource_resourceRequest_IOException() throws Exception
    {
        when(mockAccessTokenProvider.getAccessToken(Arrays.asList("listall"))).thenReturn(mockAccessToken);
        when(mockHttpUtilProvider.getHttpClient()).thenReturn(mockCloseableHttpClient);
        try
        {
            Mockito.doThrow(new IOException()).when(mockCloseableHttpClient).execute(Mockito.isA(HttpGet.class));
        }
        catch (IOException e1)
        {
            e1.printStackTrace();
        }
        when(mockCloseableHttpResponse.getStatusLine()).thenReturn(statusLine);
        when(statusLine.getStatusCode()).thenReturn(500);
        Gson gson = new Gson();
        ResopnseJson responseJson = new ResopnseJson();
        Task task = new Task();
        task.setId("1");
        task.setTitle("title");
        List<Task> tasks = new ArrayList<Task>();
        tasks.add(task);
        responseJson.setTasks(tasks);
        String json = gson.toJson(responseJson);
        when(mockHttpUtilProvider.getHttpResponseAsString(mockCloseableHttpResponse)).thenReturn(json);
        when(provider.getResourceEndpoint()).thenReturn("https://localhost");
        
        Response response = sampleClientResource.getResource();
        
        assertEquals(500, response.getStatus());
    }
    
    @Test
    public void getTokenForUser_success()
    {

        final List<String> scopeList = new ArrayList<String>();
        scopeList.add("create");
        scopeList.add("list");
        scopeList.add("delete");
        scopeList.add("update");
        when(httpServletRequest.getHeader("Authorization")).thenReturn("Basic dXNlcjE6cGFzc3dvcmQx");
        try
        {
            when(mockAccessTokenProvider.getAccessTokenForUser("user1", "password1", scopeList))
                    .thenReturn(mockAccessToken);
        }
        catch (AuthorizationHelperException | HttpResponseException e)
        {
            e.printStackTrace();
        }
        
        Response response = sampleClientResource.getTokenForUser(httpServletRequest);
        
        System.out.println(response);
        assertEquals(200, response.getStatus());
    }

    @Test
    public void getTokenForUser_AuthorizationHelperException()
    {

        final List<String> scopeList = new ArrayList<String>();
        scopeList.add("create");
        scopeList.add("list");
        scopeList.add("delete");
        scopeList.add("update");
        when(httpServletRequest.getHeader("Authorization")).thenReturn("Basic dXNlcjE6cGFzc3dvcmQx");
        try
        {
            Mockito.doThrow(new AuthorizationHelperException("exception")).when(mockAccessTokenProvider)
                    .getAccessTokenForUser("user1", "password1", scopeList);
        }
        catch (AuthorizationHelperException | HttpResponseException e)
        {
            e.printStackTrace();
        }
        
        Response response = sampleClientResource.getTokenForUser(httpServletRequest);
        
        System.out.println(response);
        assertEquals(500, response.getStatus());
    }

    @Test
    public void getTokenForUser_HttpResponseException()
    {

        final List<String> scopeList = new ArrayList<String>();
        scopeList.add("create");
        scopeList.add("list");
        scopeList.add("delete");
        scopeList.add("update");
        when(httpServletRequest.getHeader("Authorization")).thenReturn("Basic dXNlcjE6cGFzc3dvcmQx");
        try
        {
            Mockito.doThrow(new HttpResponseException(500, "exception")).when(mockAccessTokenProvider)
                    .getAccessTokenForUser("user1", "password1", scopeList);
        }
        catch (AuthorizationHelperException | HttpResponseException e)
        {
            e.printStackTrace();
        }
        
        Response response = sampleClientResource.getTokenForUser(httpServletRequest);
        
        System.out.println(response);
        assertEquals(500, response.getStatus());
    }

    @Test
    public void getTokenForUser_unauthorized()
    {
        final List<String> scopeList = new ArrayList<String>();
        scopeList.add("create");
        scopeList.add("list");
        scopeList.add("delete");
        scopeList.add("update");
        try
        {
            when(mockAccessTokenProvider.getAccessTokenForUser("user1", "password1", scopeList))
                    .thenReturn(mockAccessToken);
        }
        catch (AuthorizationHelperException | HttpResponseException e)
        {
            e.printStackTrace();
        }
        
        Response response = sampleClientResource.getTokenForUser(httpServletRequest);
        
        System.out.println(response);
        assertEquals(401, response.getStatus());
    }
}
