// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.sps;

import static org.mockito.Mockito.when;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.sps.data.AuthenticationInformation;
import com.google.sps.servlets.LoginStatusServlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
public final class LoginStatusServletTest {
  private static final String DOMAIN_NAME = "gmail.com";
  private static final String USER_EMAIL = "test@gmail.com";
  private static final String USER_ID = "testID";

  private static final String HOME_PAGE_URL = "/";
  private static final String LOGIN_PAGE_URL = "/login.html";

  private static final String LOGIN_URL = "/_ah/login?continue\u003d%2F";
  private static final String LOGOUT_URL = "/_ah/logout?continue\u003d%2Flogin.html";

  private static final AuthenticationInformation LOGGED_OUT_INFORMATION =
      new AuthenticationInformation(LOGIN_URL);
  private static final AuthenticationInformation LOGGED_IN_INFORMATION =
      new AuthenticationInformation(LOGOUT_URL, USER_EMAIL);

  // Uses local UserService.
  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalUserServiceTestConfig())
          .setEnvEmail(USER_EMAIL)
          .setEnvAuthDomain(DOMAIN_NAME)
          .setEnvAttributes(new HashMap(
              ImmutableMap.of("com.google.appengine.api.users.UserService.user_id_key", USER_ID)));

  @Mock private HttpServletRequest request;
  @Mock private HttpServletResponse response;

  private LoginStatusServlet servlet;
  private UserService userService;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    helper.setUp();
    userService = UserServiceFactory.getUserService();

    servlet = new LoginStatusServlet(userService);
  }

  @After
  public void tearDown() {
    helper.tearDown();
  }

  @Test
  public void doGetIfUserIsNotLoggedIn() throws IOException {
    helper.setEnvIsLoggedIn(false);

    StringWriter stringWriter = new StringWriter();
    PrintWriter writer = new PrintWriter(stringWriter);
    when(response.getWriter()).thenReturn(writer);

    servlet.doGet(request, response);
    writer.flush();

    String actual = getJsonResponse(stringWriter);
    String expected = new Gson().toJson(LOGGED_OUT_INFORMATION);
    Assert.assertEquals(expected, actual);
  }

  @Test
  public void doGetIfUserIsLoggedIn() throws IOException {
    helper.setEnvIsLoggedIn(true);

    StringWriter stringWriter = new StringWriter();
    PrintWriter writer = new PrintWriter(stringWriter);
    when(response.getWriter()).thenReturn(writer);

    servlet.doGet(request, response);
    writer.flush();

    String actual = getJsonResponse(stringWriter);
    String expected = new Gson().toJson(LOGGED_IN_INFORMATION);
    Assert.assertEquals(expected, actual);
  }

  /**
   * Removes the new line at the end of the response to compare to the expected String.
   */
  private String getJsonResponse(StringWriter stringWriter) {
    return stringWriter.toString().replace("\n", "");
  }
}

@@ -3470,32 +3470,16 @@
 ctual = 
-getJsonResponse(
 stringWr
@@ -3474,32 +3474,42 @@
 l = stringWriter
+.toString(
 );%0A    String ex
@@ -3517,33 +3517,39 @@
 ected = 
-new Gson().toJson
+getExpectedJsonResponse
 (LOGGED_
@@ -3956,32 +3956,16 @@
 ctual = 
-getJsonResponse(
 stringWr
@@ -3964,24 +3964,34 @@
 stringWriter
+.toString(
 );%0A    Strin
@@ -4007,25 +4007,31 @@
 d = 
-new Gson().toJson
+getExpectedJsonResponse
 (LOG
@@ -4114,55 +4114,118 @@
   * 
-Removes the new line at the end of the response
+Converts the expected authentication information object into a JSON string and adds a new line%0A   * at the end
  to 
@@ -4243,23 +4243,23 @@
 the 
-expected String
+actual response
 .%0A  
@@ -4282,16 +4282,24 @@
 ring get
+Expected
 JsonResp
@@ -4307,89 +4307,125 @@
 nse(
-StringWriter stringWriter) %7B%0A    return stringWriter.toString().replace(%22%5Cn%22, %22%22)
+AuthenticationInformation authenticationInformation) %7B%0A    return new Gson().toJson(authenticationInformation) + %22%5Cn%22
 ;%0A  

Add newline to expected login servlet response instead of removing it from the actual response.