/*
 * 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.ozone.om.snapshot;

import com.google.common.collect.ImmutableMap;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.utils.db.Table;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
import org.apache.hadoop.ozone.om.SnapshotChainManager;
import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
import org.apache.hadoop.util.Time;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_DB_DIRS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * Tests SnapshotChain that stores in chronological order
 * Ozone object storage snapshots.  There exist two types
 * of chains provided by the SnapshotChainManager
 * i.) path based snapshots - a list of snapshots taken for a given bucket
 * ii.) global snapshots - a list of every snapshot taken in chrono order
 */
public class TestSnapshotChain {
  private OMMetadataManager omMetadataManager;
  private Map<UUID, SnapshotInfo> snapshotIdToSnapshotInfoMap;
  private SnapshotChainManager chainManager;

  @TempDir
  private File folder;

  @BeforeEach
  public void setup() throws Exception {
    OzoneConfiguration conf = new OzoneConfiguration();
    conf.set(OZONE_OM_DB_DIRS, folder.toString());
    omMetadataManager = new OmMetadataManagerImpl(conf, null);
    snapshotIdToSnapshotInfoMap = new HashMap<>();
    chainManager = new SnapshotChainManager(omMetadataManager);
  }

  private SnapshotInfo createSnapshotInfo(UUID snapshotID,
                                          UUID pathPrevID,
                                          UUID globalPrevID,
                                          long creationTime) {
    return new SnapshotInfo.Builder()
        .setSnapshotId(snapshotID)
        .setName("test")
        .setVolumeName("vol1")
        .setBucketName("bucket1")
        .setSnapshotStatus(SnapshotInfo.SnapshotStatus.SNAPSHOT_ACTIVE)
        .setCreationTime(creationTime)
        .setDeletionTime(-1L)
        .setPathPreviousSnapshotId(pathPrevID)
        .setGlobalPreviousSnapshotId(globalPrevID)
        .setSnapshotPath(String.join("/", "vol1", "bucket1"))
        .setCheckpointDir("checkpoint.testdir")
        .build();
  }

  private void deleteSnapshot(UUID snapshotID) throws IOException {
    SnapshotInfo sinfo = null;
    final String snapshotPath = "vol1/bucket1";
    // reset the next snapshotInfo.globalPreviousSnapshotID
    // to the previous in the entry to be deleted.
    if (chainManager.hasNextGlobalSnapshot(snapshotID)) {
      sinfo = snapshotIdToSnapshotInfoMap.get(
          chainManager.nextGlobalSnapshot(snapshotID));
      if (chainManager.hasPreviousGlobalSnapshot(snapshotID)) {
        sinfo.setGlobalPreviousSnapshotId(
            chainManager.previousGlobalSnapshot(snapshotID));
      } else {
        sinfo.setGlobalPreviousSnapshotId(null);
      }
      snapshotIdToSnapshotInfoMap.put(sinfo.getSnapshotId(), sinfo);
    }
    // reset the next snapshotInfo.pathPreviousSnapshotID
    // to the previous in the entry to be deleted.
    if (chainManager.hasNextPathSnapshot(snapshotPath, snapshotID)) {
      sinfo = snapshotIdToSnapshotInfoMap.get(
          chainManager.nextPathSnapshot(snapshotPath, snapshotID));

      if (chainManager.hasPreviousPathSnapshot(snapshotPath, snapshotID)) {
        sinfo.setPathPreviousSnapshotId(
            chainManager.previousPathSnapshot(snapshotPath, snapshotID));
      } else {
        sinfo.setPathPreviousSnapshotId(null);
      }
      snapshotIdToSnapshotInfoMap.put(sinfo.getSnapshotId(), sinfo);
    }

    UUID latestGlobalSnapshot = chainManager.getLatestGlobalSnapshotId();
    // append snapshot to the sinfos (the end).
    if (latestGlobalSnapshot != null) {
      sinfo = snapshotIdToSnapshotInfoMap.get(snapshotID);
      sinfo.setGlobalPreviousSnapshotId(latestGlobalSnapshot);
      UUID latestPathSnapshot = chainManager.getLatestPathSnapshotId(
          String.join("/", "vol1", "bucket1"));
      if (latestPathSnapshot != null) {
        sinfo.setPathPreviousSnapshotId(latestPathSnapshot);
      }
      snapshotIdToSnapshotInfoMap.put(snapshotID, sinfo);
    }
    chainManager.deleteSnapshot(snapshotIdToSnapshotInfoMap.get(snapshotID));
  }

  @Test
  public void testAddSnapshot() throws Exception {
    final String snapshotPath = "vol1/bucket1";
    // add three snapshots
    UUID snapshotID1 = UUID.randomUUID();
    UUID snapshotID2 = UUID.randomUUID();
    UUID snapshotID3 = UUID.randomUUID();

    ArrayList<UUID> snapshotIDs = new ArrayList<>();
    snapshotIDs.add(snapshotID1);
    snapshotIDs.add(snapshotID2);
    snapshotIDs.add(snapshotID3);

    UUID prevSnapshotID = null;
    List<Integer> times = Arrays.asList(1, 2, 0);
    int timeIdx = 0;
    // add 3 snapshots
    for (UUID snapshotID : snapshotIDs) {
      chainManager.addSnapshot(createSnapshotInfo(
          snapshotID,
          prevSnapshotID,
          prevSnapshotID, times.get(timeIdx++)));
      prevSnapshotID = snapshotID;
    }

    assertEquals(snapshotID3, chainManager.getLatestGlobalSnapshotId());
    assertEquals(snapshotID3, chainManager.getLatestPathSnapshotId(
        String.join("/", "vol1", "bucket1")));

    int i = 0;
    UUID curID = snapshotIDs.get(i);
    while (chainManager.hasNextGlobalSnapshot(curID)) {
      i++;
      assertEquals(snapshotIDs.get(i), chainManager.nextGlobalSnapshot(curID));
      curID = snapshotIDs.get(i);
    }

    curID = snapshotIDs.get(i);
    while (chainManager.hasPreviousGlobalSnapshot(curID)) {
      i--;
      assertEquals(snapshotIDs.get(i),
          chainManager.previousGlobalSnapshot(curID));
      curID = snapshotIDs.get(i);
    }

    i = 0;
    curID = snapshotIDs.get(i);
    while (chainManager.hasNextPathSnapshot(snapshotPath, curID)) {
      i++;
      assertEquals(snapshotIDs.get(i),
          chainManager.nextPathSnapshot(snapshotPath, curID));
      curID = snapshotIDs.get(i);
    }

    curID = snapshotIDs.get(i);
    while (chainManager.hasPreviousPathSnapshot(snapshotPath,
        curID)) {
      i--;
      assertEquals(snapshotIDs.get(i),
          chainManager.previousPathSnapshot(snapshotPath, curID));
      curID = snapshotIDs.get(i);
    }
  }

  @Test
  public void testDeleteSnapshot() throws Exception {
    // add three snapshots
    UUID snapshotID1 = UUID.randomUUID();
    UUID snapshotID2 = UUID.randomUUID();
    UUID snapshotID3 = UUID.randomUUID();

    ArrayList<UUID> snapshotIDs = new ArrayList<>();
    snapshotIDs.add(snapshotID1);
    snapshotIDs.add(snapshotID2);
    snapshotIDs.add(snapshotID3);

    UUID prevSnapshotID = null;
    List<Integer> times = Arrays.asList(1, 2, 0);
    int timeIdx = 0;
    // add 3 snapshots
    for (UUID snapshotID : snapshotIDs) {
      snapshotIdToSnapshotInfoMap.put(snapshotID,
          createSnapshotInfo(
              snapshotID,
              prevSnapshotID,
              prevSnapshotID, times.get(timeIdx++)));

      chainManager.addSnapshot(snapshotIdToSnapshotInfoMap.get(snapshotID));
      prevSnapshotID = snapshotID;
    }

    // delete snapshotID2
    // should have snapshots ID1 and ID3 in chain

    deleteSnapshot(snapshotID2);
    // start with first snapshot in snapshot chain
    assertFalse(chainManager.hasPreviousGlobalSnapshot(snapshotID1));
    assertTrue(chainManager.hasNextGlobalSnapshot(snapshotID1));
    assertFalse(chainManager.hasNextGlobalSnapshot(snapshotID3));
    assertEquals(snapshotID3,
        chainManager.nextGlobalSnapshot(snapshotID1));

    // add snapshotID2 and delete snapshotID1
    // should have snapshotID3 and snapshotID2
    deleteSnapshot(snapshotID1);
    chainManager.addSnapshot(snapshotIdToSnapshotInfoMap.get(snapshotID2));

    assertFalse(chainManager.hasPreviousGlobalSnapshot(snapshotID3));
    assertTrue(chainManager.hasNextGlobalSnapshot(snapshotID3));
    assertEquals(snapshotID2, chainManager.nextGlobalSnapshot(snapshotID3));
    assertFalse(chainManager.hasNextGlobalSnapshot(snapshotID2));
    assertEquals(snapshotID3, chainManager.previousGlobalSnapshot(snapshotID2));
  }

  @ParameterizedTest
  @ValueSource(booleans = {true, false})
  public void testChainFromLoadFromTable(boolean increasingTIme)
      throws Exception {
    Table<String, SnapshotInfo> snapshotInfo =
            omMetadataManager.getSnapshotInfoTable();

    // add two snapshots to the snapshotInfo
    UUID snapshotID1 = UUID.randomUUID();
    UUID snapshotID2 = UUID.randomUUID();
    List<UUID> snapshotIDs = new ArrayList<>();
    snapshotIDs.add(snapshotID1);
    snapshotIDs.add(snapshotID2);
    List<SnapshotInfo> snapshotInfoList = new ArrayList<>();

    UUID prevSnapshotID = null;
    long time = System.currentTimeMillis();
    for (UUID snapshotID : snapshotIDs) {
      SnapshotInfo snapInfo = createSnapshotInfo(snapshotID, prevSnapshotID,
          prevSnapshotID, increasingTIme ? time++ : time--);
      snapshotInfo.put(snapshotID.toString(), snapInfo);
      prevSnapshotID = snapshotID;
      snapshotInfoList.add(snapInfo);
    }

    chainManager = new SnapshotChainManager(omMetadataManager);
    assertFalse(chainManager.isSnapshotChainCorrupted());
    // check if snapshots loaded correctly from snapshotInfoTable
    assertEquals(snapshotID2, chainManager.getLatestGlobalSnapshotId());
    assertEquals(snapshotID2, chainManager.nextGlobalSnapshot(snapshotID1));
    assertEquals(snapshotID1, chainManager.previousPathSnapshot(String
        .join("/", "vol1", "bucket1"), snapshotID2));
    assertThrows(NoSuchElementException.class,
        () -> chainManager.nextGlobalSnapshot(snapshotID2));
    assertThrows(NoSuchElementException.class,
        () -> chainManager.previousPathSnapshot(String
            .join("/", "vol1", "bucket1"), snapshotID1));

    UUID snapshotID3 = UUID.randomUUID();
    SnapshotInfo snapshotInfo3 = createSnapshotInfo(snapshotID3, prevSnapshotID,
        prevSnapshotID, Time.now());
    // Add and delete snapshot to make sure snapshot chain is correct.
    chainManager.addSnapshot(snapshotInfo3);
    chainManager.deleteSnapshot(snapshotInfoList.get(0));
    assertEquals(snapshotID3, chainManager.getLatestGlobalSnapshotId());
    assertThrows(NoSuchElementException.class,
        () -> chainManager.nextGlobalSnapshot(snapshotID1));
  }

  private static Stream<? extends Arguments> invalidSnapshotChain() {
    List<UUID> nodes = IntStream.range(0, 5)
        .mapToObj(i -> UUID.randomUUID())
        .collect(Collectors.toList());
    return Stream.of(
        Arguments.of(nodes, Named.of("Disconnected Snapshot Chain",
            ImmutableMap.of(
                nodes.get(1), nodes.get(0),
                nodes.get(2), nodes.get(1),
                nodes.get(4), nodes.get(3)))),
        Arguments.of(nodes, Named.of("Complete Cyclic Snapshot Chain",
            ImmutableMap.of(
                nodes.get(0), nodes.get(4),
                nodes.get(1), nodes.get(0),
                nodes.get(2), nodes.get(1),
                nodes.get(3), nodes.get(2),
                nodes.get(4), nodes.get(3)))),
        Arguments.of(nodes, Named.of("Partial Cyclic Snapshot Chain",
            ImmutableMap.of(
                nodes.get(0), nodes.get(3),
                nodes.get(1), nodes.get(0),
                nodes.get(2), nodes.get(1),
                nodes.get(3), nodes.get(2),
                nodes.get(4), nodes.get(3)))),
        Arguments.of(nodes, Named.of("Diverged Snapshot Chain",
            ImmutableMap.of(nodes.get(1), nodes.get(0),
                nodes.get(2), nodes.get(1),
                nodes.get(3), nodes.get(2),
                nodes.get(4), nodes.get(2))))
    );
  }

  @ParameterizedTest
  @MethodSource("invalidSnapshotChain")
  public void testInvalidGlobalChainFromLoadFromTable(
      List<UUID> snapshotIDs, Map<UUID, UUID> snapshotChain) throws Exception {
    Table<String, SnapshotInfo> snapshotInfo =
        omMetadataManager.getSnapshotInfoTable();
    for (UUID snapshotID : snapshotIDs) {
      snapshotInfo.put(snapshotID.toString(),
          createSnapshotInfo(snapshotID, snapshotChain.get(snapshotID),
              snapshotChain.get(snapshotID), System.currentTimeMillis()));
    }
    chainManager = new SnapshotChainManager(omMetadataManager);

    assertTrue(chainManager.isSnapshotChainCorrupted());

    SnapshotInfo snapInfo = createSnapshotInfo(UUID.randomUUID(),
        UUID.randomUUID(),
        UUID.randomUUID(),
        System.currentTimeMillis());
    IOException createException = assertThrows(IOException.class,
            () -> chainManager.addSnapshot(snapInfo));
    assertEquals("Snapshot chain is corrupted.", createException.getMessage());
    if (!snapshotIDs.isEmpty()) {
      IOException deleteException =
          assertThrows(IOException.class,
              () -> chainManager.deleteSnapshot(
                  snapshotInfo.get(snapshotIDs.get(0).toString())));
      assertEquals("Snapshot chain is corrupted.",
          deleteException.getMessage());
    }
  }

  @ParameterizedTest
  @MethodSource("invalidSnapshotChain")
  public void testInvalidChainFromLoadFromTable(List<UUID> snapshotIDs,
      Map<UUID, UUID> snapshotChain) throws Exception {
    Table<String, SnapshotInfo> snapshotInfo =
        omMetadataManager.getSnapshotInfoTable();
    UUID prevSnapshotId = null;
    for (UUID snapshotID : snapshotIDs) {
      snapshotInfo.put(snapshotID.toString(),
          createSnapshotInfo(snapshotID, snapshotChain.get(snapshotID),
              prevSnapshotId, System.currentTimeMillis()));
      prevSnapshotId = snapshotID;
    }
    chainManager = new SnapshotChainManager(omMetadataManager);
    assertTrue(chainManager.isSnapshotChainCorrupted());

    SnapshotInfo snapInfo = createSnapshotInfo(UUID.randomUUID(),
        UUID.randomUUID(),
        UUID.randomUUID(),
        System.currentTimeMillis());
    IOException createException = assertThrows(IOException.class,
            () -> chainManager.addSnapshot(snapInfo));
    assertEquals("Snapshot chain is corrupted.", createException.getMessage());
    if (!snapshotIDs.isEmpty()) {
      IOException deleteException =
          assertThrows(IOException.class,
              () -> chainManager.deleteSnapshot(
                  snapshotInfo.get(snapshotIDs.get(0).toString())));
      assertEquals("Snapshot chain is corrupted.",
          deleteException.getMessage());
    }
  }
}
