/*
 * 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.internal.cache.eviction;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.List;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.internal.cache.InternalRegion;
import org.apache.geode.internal.lang.SystemPropertyHelper;
import org.apache.geode.test.junit.categories.EvictionTest;

/**
 * This class tests the LRUCapacityController's core clock algorithm.
 */
@Category({EvictionTest.class})
public class LRUListWithSyncSortingIntegrationTest {

  @Rule
  public TestName testName = new TestName();

  @Rule
  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();

  private InternalRegion region;
  private LRUListWithSyncSorting evictionList;
  private List<EvictionNode> nodes;

  @Before
  public void setUp() throws Exception {
    region = createRegion();
    evictionList = getEvictionList(region, new TestEvictionController());
    nodes = new ArrayList<>();
    IntStream.range(0, 10).forEach(i -> {
      EvictionNode node = new LRUTestEntry(i);
      nodes.add(node);
      evictionList.appendEntry(node);
    });
  }

  @Test
  public void testAddEvictionList() throws Exception {
    IntStream.range(0, 10).forEach(i -> {
      LRUTestEntry entry = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(entry.id()).as("check node ids in order").isEqualTo(i);
    });
    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void testEvicted() throws Exception {
    actOnEvenNodes(i -> evictionList.destroyEntry(nodes.get(i)));

    actOnOddNodes(i -> {
      LRUTestEntry node = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(node.id()).as("check node ids in order").isEqualTo(i);
    });

    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void testRecentlyUsed() throws Exception {
    actOnEvenNodes(i -> nodes.get(i).setRecentlyUsed(region));

    actOnOddNodes(i -> {
      LRUTestEntry node = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(node.id()).as("check non-recently used entries returned first").isEqualTo(i);
    });

    actOnEvenNodes(i -> {
      LRUTestEntry node = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(node.id()).as("check recently used entries returned last").isEqualTo(i);
    });

    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void testRemoveHead() throws Exception {
    evictionList.destroyEntry(nodes.get(0));
    IntStream.range(1, 10).forEach(i -> {
      LRUTestEntry entry = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(entry.id()).as("all but first node should remain").isEqualTo(i);
    });

    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void testRemoveMiddle() throws Exception {
    evictionList.destroyEntry(nodes.get(5));
    IntStream.range(0, 5).forEach(i -> {
      LRUTestEntry entry = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(entry.id()).as("nodes before removed one should remain").isEqualTo(i);
    });

    IntStream.range(6, 10).forEach(i -> {
      LRUTestEntry entry = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(entry.id()).as("nodes after removed one should remain").isEqualTo(i);
    });
    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void testRemoveTail() throws Exception {
    evictionList.destroyEntry(nodes.get(9));
    IntStream.range(0, 9).forEach(i -> {
      LRUTestEntry entry = (LRUTestEntry) evictionList.getEvictableEntry();
      assertThat(entry.id()).as("all but first node should remain").isEqualTo(i);
    });

    assertThat(evictionList.getEvictableEntry()).as("check list is now empty").isNull();
  }

  @Test
  public void doesNotEvictRecentlyUsedEntryIfUnderLimit() throws Exception {
    nodes.get(0).setRecentlyUsed(region);
    assertThat(evictionList.getEvictableEntry()).isSameAs(nodes.get(1));
    assertThat(evictionList.size()).isEqualTo(9);
  }

  @Test
  public void getEvictableEntryReturnsRecentlyUsedNodeAfterSearchMaxEntriesExceeded()
      throws Exception {
    IntStream.range(10, 16).forEach(i -> {
      EvictionNode node = new LRUTestEntry(i);
      nodes.add(node);
      evictionList.appendEntry(node);
    });

    IntStream.range(0, 16).forEach(i -> nodes.get(i).setRecentlyUsed(region));
    assertThat(evictionList.getEvictableEntry()).isSameAs(nodes.get(15));
  }

  private LRUListWithSyncSorting getEvictionList(Region region, EvictionController eviction) {
    System.setProperty("geode." + SystemPropertyHelper.EVICTION_SCAN_ASYNC, "false");
    System.setProperty("geode." + SystemPropertyHelper.EVICTION_SEARCH_MAX_ENTRIES, "15");
    return (LRUListWithSyncSorting) new EvictionListBuilder(eviction).create();
  }

  private InternalRegion createRegion() throws Exception {
    Cache cache = new CacheFactory().set("locators", "").set("mcast-port", "0").create();
    return (InternalRegion) cache.createRegionFactory(RegionShortcut.PARTITION)
        .create(testName.getMethodName());
  }

  private void actOnEvenNodes(IntConsumer s) {
    IntStream.range(0, 10).filter(i -> i % 2 == 0).forEach(s);
  }

  private void actOnOddNodes(IntConsumer s) {
    IntStream.range(0, 10).filter(i -> i % 2 == 1).forEach(s);
  }
}
