/*
 * 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.samza.webapp;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.Container;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.util.ConverterUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.samza.Partition;
import org.apache.samza.SamzaException;
import org.apache.samza.clustermanager.SamzaApplicationState;
import org.apache.samza.clustermanager.SamzaResource;
import org.apache.samza.config.Config;
import org.apache.samza.config.MapConfig;
import org.apache.samza.container.TaskName;
import org.apache.samza.container.grouper.task.GroupByContainerCount;
import org.apache.samza.coordinator.JobModelManager;
import org.apache.samza.job.model.ContainerModel;
import org.apache.samza.job.model.JobModel;
import org.apache.samza.job.model.TaskModel;
import org.apache.samza.job.yarn.SamzaAppMasterMetrics;
import org.apache.samza.job.yarn.YarnAppState;
import org.apache.samza.job.yarn.YarnContainer;
import org.apache.samza.metrics.MetricsRegistryMap;
import org.apache.samza.serializers.model.SamzaObjectMapper;
import org.apache.samza.system.SystemStream;
import org.apache.samza.system.SystemStreamPartition;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;


public class TestApplicationMasterRestClient {
  private static final String AM_HOST_NAME = "dummyHost";
  private static final int AM_RPC_PORT = 1337;
  private static final int AM_HTTP_PORT = 7001;
  private static final String YARN_CONTAINER_ID_1 = "container_e38_1510966221296_0007_01_000001";
  private static final String YARN_CONTAINER_ID_2 = "container_e38_1510966221296_0007_01_000002";
  private static final String YARN_CONTAINER_ID_3 = "container_e38_1510966221296_0007_01_000003";
  private static final String APP_ATTEMPT_ID = "appattempt_1510966221296_0007_000001";

  private final ObjectMapper jsonMapper = SamzaObjectMapper.getObjectMapper();

  private CloseableHttpClient mockClient;

  @Before
  public void setup() {
    mockClient = mock(CloseableHttpClient.class);
  }

  @Rule
  public ExpectedException expectedException = ExpectedException.none(); // Enables us to verify the exception message

  @Test
  public void testGetMetricsSuccess() throws IOException {
    SamzaApplicationState samzaAppState = createSamzaApplicationState();

    MetricsRegistryMap registry = new MetricsRegistryMap();
    assignMetricValues(samzaAppState, registry);

    String response = ApplicationMasterRestServlet.getMetrics(jsonMapper, registry);
    setupMockClientResponse(HttpStatus.SC_OK, "Success", response);

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    Map<String, Map<String, Object>> metricsResult = client.getMetrics();

    String group = SamzaAppMasterMetrics.class.getCanonicalName();
    assertEquals(1, metricsResult.size());
    assertTrue(metricsResult.containsKey(group));

    Map<String, Object> amMetricsGroup = metricsResult.get(group);
    assertEquals(7, amMetricsGroup.size());
    assertEquals(samzaAppState.runningProcessors.size(),  amMetricsGroup.get("running-containers"));
    assertEquals(samzaAppState.neededProcessors.get(),    amMetricsGroup.get("needed-containers"));
    assertEquals(samzaAppState.completedProcessors.get(), amMetricsGroup.get("completed-containers"));
    assertEquals(samzaAppState.failedContainers.get(),    amMetricsGroup.get("failed-containers"));
    assertEquals(samzaAppState.releasedContainers.get(),  amMetricsGroup.get("released-containers"));
    assertEquals(samzaAppState.processorCount.get(),      amMetricsGroup.get("container-count"));
    assertEquals(samzaAppState.jobHealthy.get() ? 1 : 0,  amMetricsGroup.get("job-healthy"));
  }

  @Test
  public void testGetMetricsError() throws IOException {
    setupErrorTest("metrics");

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    client.getMetrics();
  }

  @Test
  public void testGetTaskContextSuccess() throws IOException {
    ContainerId containerId = ConverterUtils.toContainerId(YARN_CONTAINER_ID_1);
    YarnAppState yarnAppState = createYarnAppState(containerId);

    String response = ApplicationMasterRestServlet.getTaskContext(jsonMapper, yarnAppState);
    setupMockClientResponse(HttpStatus.SC_OK, "Success", response);

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    Map<String, Object> taskContextResult = client.getTaskContext();

    assertEquals(2, taskContextResult.size());
    assertEquals(2, taskContextResult.get("task-id"));
    assertEquals(containerId.toString(), taskContextResult.get("name"));
  }

  @Test
  public void testTaskContextError() throws IOException {
    setupErrorTest("task context");

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    client.getTaskContext();
  }

  @Test
  public void testGetAmStateSuccess() throws IOException {
    SamzaApplicationState samzaAppState = createSamzaApplicationState();

    ApplicationAttemptId attemptId = ConverterUtils.toApplicationAttemptId(APP_ATTEMPT_ID);
    ContainerId containerId = ConverterUtils.toContainerId(YARN_CONTAINER_ID_1);
    YarnAppState yarnAppState = createYarnAppState(containerId);

    String response = ApplicationMasterRestServlet.getAmState(jsonMapper, samzaAppState, yarnAppState);
    setupMockClientResponse(HttpStatus.SC_OK, "Success", response);

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    Map<String, Object> amStateResult = client.getAmState();

    assertEquals(4, amStateResult.size());
    assertEquals(String.format("%s:%s", yarnAppState.nodeHost, yarnAppState.rpcUrl.getPort()), amStateResult.get("host"));
    assertEquals(containerId.toString(), amStateResult.get("container-id"));
    // Can only validate the keys because up-time changes everytime it's requested
    assertEquals(buildExpectedContainerResponse(yarnAppState.runningProcessors, samzaAppState).keySet(),
        ((Map<String, Object>) amStateResult.get("containers")).keySet());
    assertEquals(attemptId.toString(), amStateResult.get("app-attempt-id"));
  }

  @Test
  public void testGetAmStateError() throws IOException {
    setupErrorTest("AM state");

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    client.getAmState();
  }

  @Test
  public void testGetConfigSuccess() throws IOException {
    SamzaApplicationState samzaAppState = createSamzaApplicationState();

    Map<String, String> configMap = ImmutableMap.of("key1", "value1", "key2", "value2");
    Config config = new MapConfig(configMap);

    String response = ApplicationMasterRestServlet.getConfig(jsonMapper, config);
    setupMockClientResponse(HttpStatus.SC_OK, "Success", response);

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    Map<String, Object> configResult = client.getConfig();

    assertEquals(configMap, configResult);
  }

  @Test
  public void testGetConfigError() throws IOException {
    setupErrorTest("config");

    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    client.getConfig();
  }

  @Test
  public void testCloseMethodClosesHttpClient() throws IOException {
    ApplicationMasterRestClient client = new ApplicationMasterRestClient(mockClient, AM_HOST_NAME, AM_RPC_PORT);
    client.close();

    verify(mockClient).close();
  }

  private void setupMockClientResponse(int statusCode, String statusReason, String responseBody) throws IOException {
    StatusLine statusLine = mock(StatusLine.class);
    when(statusLine.getStatusCode()).thenReturn(statusCode);
    when(statusLine.getReasonPhrase()).thenReturn(statusReason);

    HttpEntity entity = mock(HttpEntity.class);
    when(entity.getContent()).thenReturn(new ReaderInputStream(new StringReader(responseBody)));

    CloseableHttpResponse response = mock(CloseableHttpResponse.class);
    when(response.getStatusLine()).thenReturn(statusLine);
    when(response.getEntity()).thenReturn(entity);

    when(mockClient.execute(any(HttpHost.class), any(HttpGet.class))).thenReturn(response);
  }

  private SamzaApplicationState createSamzaApplicationState() {
    HashMap<String, ContainerModel> containers = generateContainers();

    JobModel mockJobModel = mock(JobModel.class);
    when(mockJobModel.getContainers()).thenReturn(containers);
    JobModelManager mockJobModelManager = mock(JobModelManager.class);
    when(mockJobModelManager.jobModel()).thenReturn(mockJobModel);

    SamzaApplicationState samzaApplicationState = new SamzaApplicationState(mockJobModelManager);

    samzaApplicationState.runningProcessors.put(YARN_CONTAINER_ID_3,
        new SamzaResource(1, 2, "dummyNodeHost1", "dummyResourceId1"));
    samzaApplicationState.runningProcessors.put(YARN_CONTAINER_ID_2,
        new SamzaResource(2, 4, "dummyNodeHost2", "dummyResourceId2"));
    return samzaApplicationState;
  }

  private YarnAppState createYarnAppState(ContainerId containerId) throws MalformedURLException {
    YarnAppState yarnAppState = new YarnAppState(2, containerId, AM_HOST_NAME, AM_RPC_PORT, AM_HTTP_PORT);
    yarnAppState.rpcUrl = new URL(new HttpHost(AM_HOST_NAME, AM_RPC_PORT).toURI());
    yarnAppState.runningProcessors.put("0", new YarnContainer(Container.newInstance(
        ConverterUtils.toContainerId(YARN_CONTAINER_ID_2),
        ConverterUtils.toNodeIdWithDefaultPort("dummyNodeHost1"),
        "dummyNodeHttpHost1",
        null,
        null,
        null
    )));
    yarnAppState.runningProcessors.put("1", new YarnContainer(Container.newInstance(
        ConverterUtils.toContainerId(YARN_CONTAINER_ID_3),
        ConverterUtils.toNodeIdWithDefaultPort("dummyNodeHost2"),
        "dummyNodeHttpHost2",
        null,
        null,
        null
    )));
    return yarnAppState;
  }

  private HashMap<String, ContainerModel> generateContainers() {
    Set<TaskModel> taskModels = ImmutableSet.of(
        new TaskModel(new TaskName("task1"),
                      ImmutableSet.of(new SystemStreamPartition(new SystemStream("system1", "stream1"), new Partition(0))),
                      new Partition(0)),
        new TaskModel(new TaskName("task2"),
            ImmutableSet.of(new SystemStreamPartition(new SystemStream("system1", "stream1"), new Partition(1))),
            new Partition(1)));
    GroupByContainerCount grouper = new GroupByContainerCount(2);
    Set<ContainerModel> containerModels = grouper.group(taskModels);
    HashMap<String, ContainerModel> containers = new HashMap<>();
    for (ContainerModel containerModel : containerModels) {
      containers.put(containerModel.getId(), containerModel);
    }
    return containers;
  }

  private Map<String, Map<String, Object>> buildExpectedContainerResponse(Map<String, YarnContainer> runningYarnContainers,
      SamzaApplicationState samzaAppState) throws IOException {
    Map<String, Map<String, Object>> containers = new HashMap<>();

    runningYarnContainers.forEach((containerId, container) -> {
      String yarnContainerId = container.id().toString();
      Map<String, Object> containerMap = new HashMap();
      Map<TaskName, TaskModel> taskModels = samzaAppState.jobModelManager.jobModel().getContainers().get(containerId).getTasks();
      containerMap.put("yarn-address", container.nodeHttpAddress());
      containerMap.put("start-time", String.valueOf(container.startTime()));
      containerMap.put("up-time", String.valueOf(container.upTime()));
      containerMap.put("task-models", taskModels);
      containerMap.put("container-id", containerId);
      containers.put(yarnContainerId, containerMap);
    });

    return jsonMapper.readValue(jsonMapper.writeValueAsString(containers), new TypeReference<Map<String, Map<String, Object>>>() { });
  }

  private void assignMetricValues(SamzaApplicationState samzaAppState, MetricsRegistryMap registry) {
    SamzaAppMasterMetrics metrics = new SamzaAppMasterMetrics(new MapConfig(), samzaAppState, registry);
    metrics.start();
    samzaAppState.runningProcessors.put("dummyContainer",
        new SamzaResource(1, 2, AM_HOST_NAME, "dummyResourceId")); // 1 container
    samzaAppState.neededProcessors.set(2);
    samzaAppState.completedProcessors.set(3);
    samzaAppState.failedContainers.set(4);
    samzaAppState.releasedContainers.set(5);
    samzaAppState.processorCount.set(6);
    samzaAppState.jobHealthy.set(true);
  }

  private void setupErrorTest(String entityToFetch) throws IOException {
    String statusReason = "Dummy status reason";
    expectedException.expect(SamzaException.class);
    expectedException.expectMessage(String.format(
        "Error retrieving %s from host %s. Response: %s",
        entityToFetch,
        new HttpHost(AM_HOST_NAME, AM_RPC_PORT).toURI(),
        statusReason));

    setupMockClientResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, statusReason, "");
  }
}
