/*
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.hadoop.hdds.scm.cli.container;

import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.scm.client.ScmClient;
import org.apache.hadoop.hdds.scm.container.ContainerInfo;
import org.apache.hadoop.hdds.scm.container.ContainerReplicaInfo;
import org.apache.hadoop.hdds.scm.container.common.helpers.ContainerWithPipeline;
import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import picocli.CommandLine;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.LifeCycleState.CLOSED;
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;

/**
 * Tests for InfoSubCommand class.
 */
public class TestInfoSubCommand {

  private ScmClient scmClient;
  private InfoSubcommand cmd;
  private List<DatanodeDetails> datanodes;
  private Logger logger;
  private TestAppender appender;

  @Before
  public void setup() throws IOException {
    scmClient = mock(ScmClient.class);
    datanodes = createDatanodeDetails(3);
    Mockito.when(scmClient.getContainerWithPipeline(anyLong()))
        .thenReturn(getContainerWithPipeline());

    appender = new TestAppender();
    logger = Logger.getLogger(
        org.apache.hadoop.hdds.scm.cli.container.InfoSubcommand.class);
    logger.addAppender(appender);
  }

  @After
  public void after() {
    logger.removeAppender(appender);
  }

  @Test
  public void testReplicasIncludedInOutput() throws Exception {
    testReplicaIncludedInOutput(false);
  }

  @Test
  public void testReplicaIndexInOutput() throws Exception {
    testReplicaIncludedInOutput(true);
  }


  private void testReplicaIncludedInOutput(boolean includeIndex)
      throws IOException {
    Mockito.when(scmClient.getContainerReplicas(anyLong()))
        .thenReturn(getReplicas(includeIndex));
    cmd = new InfoSubcommand();
    CommandLine c = new CommandLine(cmd);
    c.parseArgs("1");
    cmd.execute(scmClient);

    // Ensure we have a line for Replicas:
    List<LoggingEvent> logs = appender.getLog();
    List<LoggingEvent> replica = logs.stream()
        .filter(m -> m.getRenderedMessage().matches("(?s)^Replicas:.*"))
        .collect(Collectors.toList());
    Assert.assertEquals(1, replica.size());

    // Ensure each DN UUID is mentioned in the message:
    for (DatanodeDetails dn : datanodes) {
      Pattern pattern = Pattern.compile(".*" + dn.getUuid().toString() + ".*",
          Pattern.DOTALL);
      Matcher matcher = pattern.matcher(replica.get(0).getRenderedMessage());
      Assert.assertTrue(matcher.matches());
    }
    // Ensure ReplicaIndex is not mentioned as it was not passed in the proto:
    Pattern pattern = Pattern.compile(".*ReplicaIndex.*",
        Pattern.DOTALL);
    Matcher matcher = pattern.matcher(replica.get(0).getRenderedMessage());
    Assert.assertEquals(includeIndex, matcher.matches());
  }

  @Test
  public void testReplicasNotOutputIfError() throws IOException {
    Mockito.when(scmClient.getContainerReplicas(anyLong()))
        .thenThrow(new IOException("Error getting Replicas"));
    cmd = new InfoSubcommand();
    CommandLine c = new CommandLine(cmd);
    c.parseArgs("1");
    cmd.execute(scmClient);

    // Ensure we have no lines for Replicas:
    List<LoggingEvent> logs = appender.getLog();
    List<LoggingEvent> replica = logs.stream()
        .filter(m -> m.getRenderedMessage().matches("(?s)^Replicas:.*"))
        .collect(Collectors.toList());
    Assert.assertEquals(0, replica.size());

    // Ensure we have an error logged:
    List<LoggingEvent> error = logs.stream()
        .filter(m -> m.getLevel() == Level.ERROR)
        .collect(Collectors.toList());
    Assert.assertEquals(1, error.size());
    Assert.assertTrue(error.get(0).getRenderedMessage()
        .matches("(?s)^Unable to retrieve the replica details.*"));
  }

  @Test
  public void testReplicasNotOutputIfErrorWithJson() throws IOException {
    Mockito.when(scmClient.getContainerReplicas(anyLong()))
        .thenThrow(new IOException("Error getting Replicas"));
    cmd = new InfoSubcommand();
    CommandLine c = new CommandLine(cmd);
    c.parseArgs("1", "--json");
    cmd.execute(scmClient);

    List<LoggingEvent> logs = appender.getLog();
    Assert.assertEquals(2, logs.size());
    String error = logs.get(0).getRenderedMessage();
    String json = logs.get(1).getRenderedMessage();

    Assert.assertTrue(error
        .matches("(?s)^Unable to retrieve the replica details.*"));
    Assert.assertFalse(json.matches("(?s).*replicas.*"));
  }

  @Test
  public void testReplicasOutputWithJson() throws IOException {
    Mockito.when(scmClient.getContainerReplicas(anyLong()))
        .thenReturn(getReplicas(true));
    testJsonOutput();
  }

  @Test
  public void testECContainerReplicasOutputWithJson() throws IOException {
    Mockito.when(scmClient.getContainerReplicas(anyLong()))
        .thenReturn(getReplicas(true));
    Mockito.when(scmClient.getContainerWithPipeline(anyLong()))
        .thenReturn(getECContainerWithPipeline());
    testJsonOutput();
  }

  private void testJsonOutput() throws IOException {
    cmd = new InfoSubcommand();
    CommandLine c = new CommandLine(cmd);
    c.parseArgs("1", "--json");
    cmd.execute(scmClient);

    List<LoggingEvent> logs = appender.getLog();
    Assert.assertEquals(1, logs.size());

    // Ensure each DN UUID is mentioned in the message after replicas:
    String json = logs.get(0).getRenderedMessage();
    Assert.assertTrue(json.matches("(?s).*replicas.*"));
    for (DatanodeDetails dn : datanodes) {
      Pattern pattern = Pattern.compile(
          ".*replicas.*" + dn.getUuid().toString() + ".*", Pattern.DOTALL);
      Matcher matcher = pattern.matcher(json);
      Assert.assertTrue(matcher.matches());
    }
    Pattern pattern = Pattern.compile(".*replicaIndex.*",
        Pattern.DOTALL);
    Matcher matcher = pattern.matcher(json);
    Assert.assertTrue(matcher.matches());
  }


  private List<ContainerReplicaInfo> getReplicas(boolean includeIndex) {
    List<ContainerReplicaInfo> replicas = new ArrayList<>();
    for (DatanodeDetails dn : datanodes) {
      ContainerReplicaInfo.Builder container
          = new ContainerReplicaInfo.Builder()
          .setContainerID(1)
          .setBytesUsed(1234)
          .setState("CLOSED")
          .setPlaceOfBirth(dn.getUuid())
          .setDatanodeDetails(dn)
          .setKeyCount(1)
          .setSequenceId(1);
      if (includeIndex) {
        container.setReplicaIndex(4);
      }
      replicas.add(container.build());
    }
    return replicas;
  }

  private ContainerWithPipeline getContainerWithPipeline() {
    Pipeline pipeline = new Pipeline.Builder()
        .setState(Pipeline.PipelineState.CLOSED)
        .setReplicationConfig(new RatisReplicationConfig(THREE))
        .setId(PipelineID.randomId())
        .setNodes(datanodes)
        .build();

    ContainerInfo container = new ContainerInfo.Builder()
        .setSequenceId(1)
        .setPipelineID(pipeline.getId())
        .setUsedBytes(1234)
        .setReplicationConfig(new RatisReplicationConfig(THREE))
        .setNumberOfKeys(1)
        .setState(CLOSED)
        .build();

    return new ContainerWithPipeline(container, pipeline);
  }

  private ContainerWithPipeline getECContainerWithPipeline() {
    Pipeline pipeline = new Pipeline.Builder()
        .setState(Pipeline.PipelineState.CLOSED)
        .setReplicationConfig(new ECReplicationConfig(3, 2))
        .setId(PipelineID.randomId())
        .setNodes(datanodes)
        .build();

    ContainerInfo container = new ContainerInfo.Builder()
        .setSequenceId(1)
        .setPipelineID(pipeline.getId())
        .setUsedBytes(1234)
        .setReplicationConfig(new RatisReplicationConfig(THREE))
        .setNumberOfKeys(1)
        .setState(CLOSED)
        .build();

    return new ContainerWithPipeline(container, pipeline);
  }

  private List<DatanodeDetails> createDatanodeDetails(int count) {
    List<DatanodeDetails> dns = new ArrayList<>();
    for (int i = 0; i < count; i++) {
      HddsProtos.DatanodeDetailsProto dnd =
          HddsProtos.DatanodeDetailsProto.newBuilder()
              .setHostName("host" + i)
              .setIpAddress("1.2.3." + i + 1)
              .setNetworkLocation("/default")
              .setNetworkName("host" + i)
              .addPorts(HddsProtos.Port.newBuilder()
                  .setName("ratis").setValue(5678).build())
              .setUuid(UUID.randomUUID().toString())
              .build();
      dns.add(DatanodeDetails.getFromProtoBuf(dnd));
    }
    return dns;
  }

  private static class TestAppender extends AppenderSkeleton {
    private final List<LoggingEvent> log = new ArrayList<>();

    @Override
    public boolean requiresLayout() {
      return false;
    }

    @Override
    protected void append(final LoggingEvent loggingEvent) {
      log.add(loggingEvent);
    }

    @Override
    public void close() {
    }

    public List<LoggingEvent> getLog() {
      return new ArrayList<>(log);
    }
  }
}
