/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.management.client;


import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.List;
import java.util.stream.Collectors;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.WebApplicationContext;

import org.apache.geode.management.api.ClusterManagementListResult;
import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.management.api.ClusterManagementService;
import org.apache.geode.management.configuration.MemberConfig;
import org.apache.geode.management.internal.rest.LocatorLauncherContextLoader;
import org.apache.geode.management.internal.rest.LocatorWebContext;
import org.apache.geode.management.runtime.MemberInformation;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;

@RunWith(SpringRunner.class)
@ContextConfiguration(locations = {"classpath*:WEB-INF/management-servlet.xml"},
    loader = LocatorLauncherContextLoader.class)
@WebAppConfiguration
public class MemberManagementServiceDUnitTest {

  @Autowired
  private WebApplicationContext webApplicationContext;

  @Rule
  public ClusterStartupRule cluster = new ClusterStartupRule(1);

  private ClusterManagementService client;
  private LocatorWebContext webContext;

  @Before
  public void before() {
    cluster.setSkipLocalDistributedSystemCleanup(true);
    webContext = new LocatorWebContext(webApplicationContext);
    client = ClusterManagementServiceBuilder.buildWithRequestFactory()
        .setRequestFactory(webContext.getRequestFactory()).build();
    cluster.startServerVM(1, webContext.getLocator().getPort());
  }

  @Test
  @WithMockUser
  public void listAllMembers() {
    MemberConfig memberConfig = new MemberConfig();
    ClusterManagementListResult<MemberConfig, MemberInformation> result = client.list(memberConfig);

    assertThat(result.isSuccessful()).isTrue();
    assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);

    List<MemberInformation> members = result.getRuntimeResult();
    assertThat(members.size()).isEqualTo(2);
    assertThat(members.stream().map(MemberInformation::getMemberName).collect(Collectors.toList()))
        .containsExactlyInAnyOrder("locator-0", "server-1");
    for (MemberInformation oneMember : members) {
      if (!oneMember.isServer()) {
        assertThat(oneMember.isCoordinator()).isTrue();
        assertThat(oneMember.getLocatorPort())
            .as("port for locator member should not be null").isNotNull().isGreaterThan(0);
        assertThat(oneMember.getCacheServerInfo().size())
            .as("locators should not have cache servers").isEqualTo(0);
      } else {
        assertThat(oneMember.isCoordinator()).isFalse();
        assertThat(oneMember.getLocatorPort()).as("port for server member should be 0")
            .isEqualTo(0);
        assertThat(oneMember.getCacheServerInfo().size())
            .as("server should have one cache server").isEqualTo(1);
        assertThat(oneMember.getCacheServerInfo().get(0).getPort()).isGreaterThan(0);
        assertThat(oneMember.getCacheServerInfo().get(0).getMaxConnections()).isGreaterThan(0);
        assertThat(oneMember.getCacheServerInfo().get(0).getMaxThreads()).isEqualTo(0);
      }
    }
  }

  @Test
  @WithMockUser
  public void getOneMember() {
    MemberConfig config = new MemberConfig();
    config.setId("server-1");
    ClusterManagementListResult<MemberConfig, MemberInformation> result = client.list(config);

    assertThat(result.isSuccessful()).isTrue();
    assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);

    List<MemberInformation> memberConfig = result.getRuntimeResult();
    assertThat(memberConfig.size()).isEqualTo(1);
  }

  @Test
  @WithMockUser
  public void getMemberStatus() {
    MemberConfig config = new MemberConfig();
    config.setId("locator-0");
    ClusterManagementListResult<MemberConfig, MemberInformation> result = client.list(config);
    assertThat(result.isSuccessful()).isTrue();
    assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);

    List<MemberInformation> members = result.getRuntimeResult();
    assertThat(members.size()).isEqualTo(1);

    MemberInformation memberConfig = members.get(0);
    assertThat(memberConfig.getInitHeapSize()).isGreaterThan(0);
    assertThat(memberConfig.getMaxHeapSize()).isGreaterThan(0);
    assertThat(memberConfig.getStatus()).isEqualTo("online");
  }

  @Test
  @WithMockUser
  public void noMatchWithJavaAPI() {
    MemberConfig config = new MemberConfig();
    // look for a member with a non-existent id
    config.setId("server");
    ClusterManagementListResult<MemberConfig, MemberInformation> result = client.list(config);
    assertThat(result.isSuccessful()).isTrue();
    assertThat(result.getStatusCode())
        .isEqualTo(ClusterManagementResult.StatusCode.OK);
    assertThat(result.getResult().size()).isEqualTo(1);
    assertThat(result.getRuntimeResult().size()).isEqualTo(0);
  }

  @Test
  @WithMockUser
  public void noMatchWithFilter() throws Exception {
    webContext.perform(get("/experimental/members?id=server"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.statusCode", is("OK")));
  }

  @Test
  @WithMockUser
  public void noMatchWithUriVariable() throws Exception {
    webContext.perform(get("/experimental/members/server"))
        .andExpect(status().isNotFound())
        .andExpect(jsonPath("$.statusCode", is("ENTITY_NOT_FOUND")))
        .andExpect(jsonPath("$.statusMessage",
            is("Member 'server' does not exist.")));
  }
}
