// Copyright (C) 2013 The Android Open Source Project
//
// 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
//
// http://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.gerrit.acceptance.rest.group;

import static com.google.gerrit.acceptance.rest.group.GroupAssert.toBoolean;
import static com.google.gerrit.acceptance.rest.group.GroupAssert.assertGroupInfo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.AccountCreator;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.RestSession;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupCache;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;

import org.apache.http.HttpStatus;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

public class GroupPropertiesIT extends AbstractDaemonTest {

  @Inject
  private AccountCreator accounts;

  @Inject
  private GroupCache groupCache;

  private TestAccount admin;
  private RestSession session;

  @Before
  public void setUp() throws Exception {
    admin = accounts.create("admin", "admin@example.com", "Administrator",
            "Administrators");
    session = new RestSession(server, admin);
  }

  @Test
  public void testGroupName() throws IOException {
    AccountGroup.NameKey adminGroupName = new AccountGroup.NameKey("Administrators");
    String url = "/groups/" + groupCache.get(adminGroupName).getGroupUUID().get() + "/name";

    // get name
    RestResponse r = session.get(url);
    String name = (new Gson()).fromJson(r.getReader(), new TypeToken<String>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals("Administrators", name);
    r.consume();

    // set name with name conflict
    GroupNameInput in = new GroupNameInput();
    in.name = "Registered Users";
    r = session.put(url, in);
    assertEquals(HttpStatus.SC_CONFLICT, r.getStatusCode());
    r.consume();

    // set name to same name
    in = new GroupNameInput();
    in.name = "Administrators";
    r = session.put(url, in);
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    r.consume();

    // rename
    in = new GroupNameInput();
    in.name = "Admins";
    r = session.put(url, in);
    String newName = (new Gson()).fromJson(r.getReader(), new TypeToken<String>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertNotNull(groupCache.get(new AccountGroup.NameKey(in.name)));
    assertNull(groupCache.get(adminGroupName));
    assertEquals(in.name, newName);
    r.consume();
  }

  @Test
  public void testGroupDescription() throws IOException {
    AccountGroup.NameKey adminGroupName = new AccountGroup.NameKey("Administrators");
    AccountGroup adminGroup = groupCache.get(adminGroupName);
    String url = "/groups/" + adminGroup.getGroupUUID().get() + "/description";

    // get description
    RestResponse r = session.get(url);
    String description = (new Gson()).fromJson(r.getReader(), new TypeToken<String>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals(adminGroup.getDescription(), description);
    r.consume();

    // set description
    GroupDescriptionInput in = new GroupDescriptionInput();
    in.description = "All users that can administrate the Gerrit Server.";
    r = session.put(url, in);
    String newDescription = (new Gson()).fromJson(r.getReader(), new TypeToken<String>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals(in.description, newDescription);
    adminGroup = groupCache.get(adminGroupName);
    assertEquals(in.description, adminGroup.getDescription());
    r.consume();

    // delete description
    r = session.delete(url);
    assertEquals(HttpStatus.SC_NO_CONTENT, r.getStatusCode());
    adminGroup = groupCache.get(adminGroupName);
    assertNull(adminGroup.getDescription());

    // set description to empty string
    in = new GroupDescriptionInput();
    in.description = "";
    r = session.put(url, in);
    assertEquals(HttpStatus.SC_NO_CONTENT, r.getStatusCode());
    adminGroup = groupCache.get(adminGroupName);
    assertNull(adminGroup.getDescription());
  }

  @Test
  public void testGroupOptions() throws IOException {
    AccountGroup.NameKey adminGroupName = new AccountGroup.NameKey("Administrators");
    AccountGroup adminGroup = groupCache.get(adminGroupName);
    String url = "/groups/" + adminGroup.getGroupUUID().get() + "/options";

    // get options
    RestResponse r = session.get(url);
    GroupOptionsInfo options = (new Gson()).fromJson(r.getReader(), new TypeToken<GroupOptionsInfo>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals(adminGroup.isVisibleToAll(), toBoolean(options.visible_to_all));
    r.consume();

    // set options
    GroupOptionsInput in = new GroupOptionsInput();
    in.visible_to_all = !adminGroup.isVisibleToAll();
    r = session.put(url, in);
    GroupOptionsInfo newOptions = (new Gson()).fromJson(r.getReader(), new TypeToken<GroupOptionsInfo>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals(in.visible_to_all, toBoolean(newOptions.visible_to_all));
    adminGroup = groupCache.get(adminGroupName);
    assertEquals(in.visible_to_all, adminGroup.isVisibleToAll());
    r.consume();
  }

  @Test
  public void testGroupOwner() throws IOException {
    AccountGroup.NameKey adminGroupName = new AccountGroup.NameKey("Administrators");
    AccountGroup adminGroup = groupCache.get(adminGroupName);
    String url = "/groups/" + adminGroup.getGroupUUID().get() + "/owner";

    // get owner
    RestResponse r = session.get(url);
    GroupInfo options = (new Gson()).fromJson(r.getReader(), new TypeToken<GroupInfo>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertGroupInfo(groupCache.get(adminGroup.getOwnerGroupUUID()), options);
    r.consume();

    // set owner by name
    GroupOwnerInput in = new GroupOwnerInput();
    in.owner = "Registered Users";
    r = session.put(url, in);
    GroupInfo newOwner = (new Gson()).fromJson(r.getReader(), new TypeToken<GroupInfo>() {}.getType());
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    assertEquals(in.owner, newOwner.name);
    adminGroup = groupCache.get(adminGroupName);
    assertGroupInfo(groupCache.get(adminGroup.getOwnerGroupUUID()), newOwner);
    r.consume();

    // set owner by UUID
    in = new GroupOwnerInput();
    in.owner = adminGroup.getGroupUUID().get();
    r = session.put(url, in);
    assertEquals(HttpStatus.SC_OK, r.getStatusCode());
    adminGroup = groupCache.get(adminGroupName);
    assertEquals(in.owner, groupCache.get(adminGroup.getOwnerGroupUUID()).getGroupUUID().get());
    r.consume();

    // set non existing owner
    in = new GroupOwnerInput();
    in.owner = "Non-Existing Group";
    r = session.put(url, in);
    assertEquals(HttpStatus.SC_UNPROCESSABLE_ENTITY, r.getStatusCode());
    r.consume();
  }

  private static class GroupNameInput {
    String name;
  }

  private static class GroupDescriptionInput {
    String description;
  }

  private static class GroupOptionsInput {
    Boolean visible_to_all;
  }

  private static class GroupOwnerInput {
    String owner;
  }
}
