// Copyright 2020 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.lecturechat.data;

import static org.junit.Assert.assertEquals;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class DatastoreAccessTest {

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
  private DatastoreAccess datastore;
  private DatastoreService service;

  // Parameters for arranging.
  private final String UNIVERSITY_A = "Uni A";
  private final String UNIVERSITY_B = "Uni B";
  private final String UNIVERSITY_C = "Uni C";
  private final String DEGREE = "Degree A";
  private final int YEAR = 1;
  private final String EVENT_TITLE_A = "Event A";
  private final String EVENT_CREATOR = "Creator A";
  private final long START_TIME = 0;
  private final long END_TIME = 0;
  private final String USER_ID = "User Id A";
  private final String USER_NAME = "User Name A";

  // Constants since we don't have access to the constants files here.
  private final String groupEntityLabel = "Group";
  private final String eventEntityLabel = "Event";
  private final String userEntityLabel = "User";

  @Before
  public void setUp() {
    helper.setUp();
    service = DatastoreServiceFactory.getDatastoreService();
    datastore = DatastoreAccess.getDatastoreAccess();
  }

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

  @Test
  public void addGroupAddsExactlyOneGroup() {
    datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);

    assertEquals(1, service.prepare(new Query(groupEntityLabel)).countEntities());
  }

  @Test
  public void addGroupDoesntAddAlreadyExistingGroup() {
    datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);

    datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);

    assertEquals(1, service.prepare(new Query(groupEntityLabel)).countEntities());
  }

  @Test
  public void getAllGroupsReturnsEmptyListIfNoGroupsInDatastore() {
    List<Group> groups = datastore.getAllGroups();

    assertEquals(0, groups.size());
  }

  @Test
  public void getAllGroupsReturnsCorrectNumberOfGroups() {
    datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);
    datastore.addGroup(UNIVERSITY_B, DEGREE, YEAR);

    List<Group> groups = datastore.getAllGroups();

    assertEquals(2, groups.size());
  }

  @Test
  public void addEventAddsExactlyOneEventToCorrectGroup() {
    long groupId = datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);

    datastore.addEventToGroup(groupId, EVENT_TITLE_A, START_TIME, END_TIME, EVENT_CREATOR);
    List<Event> events = datastore.getAllEventsFromGroup(groupId);

    assertEquals(1, service.prepare(new Query(eventEntityLabel)).countEntities());
    assertEquals(1, events.size());
  }

  @Test(expected = IllegalArgumentException.class)
  public void addEventToNonexistingGroupThrowsException() {
    long groupId = 123L;

    datastore.addEventToGroup(groupId, EVENT_TITLE_A, START_TIME, END_TIME, EVENT_CREATOR);
  }

  @Test
  public void addUserAddsExactlyOneUser() {
    datastore.addUser(USER_ID, USER_NAME);

    assertEquals(1, service.prepare(new Query(userEntityLabel)).countEntities());
  }

  @Test
  public void addUserDoesntAddExistingUser() {
    datastore.addUser(USER_ID, USER_NAME);

    datastore.addUser(USER_ID, USER_NAME);

    assertEquals(1, service.prepare(new Query(userEntityLabel)).countEntities());
  }

  @Test
  public void getCorrectNumberOfJoinedAndNotJoinedGroups() {
    long groupA = datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);
    long groupB = datastore.addGroup(UNIVERSITY_B, DEGREE, YEAR);
    long groupC = datastore.addGroup(UNIVERSITY_C, DEGREE, YEAR);
    datastore.addUser(USER_ID, USER_NAME);
    datastore.joinGroup(USER_ID, groupA);
    datastore.joinGroup(USER_ID, groupB);

    List<Group> joined = datastore.getJoinedGroups(USER_ID);
    List<Group> notJoined = datastore.getNotJoinedGroups(USER_ID);

    assertEquals(2, joined.size());
    assertEquals(1, notJoined.size());
  }
}

@@ -1721,24 +1721,124 @@
  %22Event A%22;%0A
+  private final String EVENT_TITLE_B = %22Event B%22;%0A  private final String EVENT_TITLE_C = %22Event C%22;%0A
   private fi
@@ -4981,24 +4981,900 @@
 (USER_ID);%0A%0A
+    assertEquals(2, joined.size());%0A    assertEquals(1, notJoined.size());%0A  %7D%0A%0A  @Test%0A  public void getCorrectNumberOfJoinedAndNotJoinedEvents() %7B%0A    long groupId = datastore.addGroup(UNIVERSITY_A, DEGREE, YEAR);%0A    long eventA = datastore.addEventToGroup(groupId, EVENT_TITLE_A, START_TIME, END_TIME, EVENT_CREATOR);%0A    long eventB = datastore.addEventToGroup(groupId, EVENT_TITLE_B, START_TIME, END_TIME, EVENT_CREATOR);%0A    long eventC = datastore.addEventToGroup(groupId, EVENT_TITLE_C, START_TIME, END_TIME, EVENT_CREATOR);%0A    datastore.addUser(USER_ID, USER_NAME);%0A    datastore.joinGroup(USER_ID, groupId);%0A    datastore.joinEvent(USER_ID, eventA);%0A    datastore.joinEvent(USER_ID, eventB);%0A%0A    List%3CEvent%3E joined = datastore.getAllJoinedEventsFromGroup(groupId, USER_ID);%0A    List%3CEvent%3E notJoined = datastore.getAllNotJoinedEventsFromGroup(groupId, USER_ID);%0A%0A
     assertEq

Add test for joined events