/*
 * 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.accumulo.master.tableOps.bulkVer2;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.clientImpl.AcceptableThriftTableOperationException;
import org.apache.accumulo.core.data.TableId;
import org.apache.accumulo.core.dataImpl.KeyExtent;
import org.apache.accumulo.master.tableOps.bulkVer2.PrepBulkImport.TabletIterFactory;
import org.apache.hadoop.io.Text;
import org.junit.Test;

import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

public class PrepBulkImportTest {

  KeyExtent nke(String prev, String end) {
    Text per = prev == null ? null : new Text(prev);
    Text er = end == null ? null : new Text(end);

    return new KeyExtent(TableId.of("1"), er, per);
  }

  List<KeyExtent> createExtents(Iterable<String> rowsIter) {
    List<KeyExtent> extents = new ArrayList<>();

    List<String> rows = new ArrayList<>();
    rowsIter.forEach(rows::add);

    Collections.sort(rows);
    for (int i = 0; i < rows.size(); i++) {
      extents.add(nke(i == 0 ? null : rows.get(i - 1), rows.get(i)));

    }

    extents.add(nke(rows.size() == 0 ? null : rows.get(rows.size() - 1), null));

    return extents;
  }

  Iterable<List<KeyExtent>> powerSet(KeyExtent... extents) {
    Set<Set<KeyExtent>> powerSet = Sets.powerSet(Set.copyOf(Arrays.asList(extents)));

    return Iterables.transform(powerSet, set -> {
      List<KeyExtent> list = new ArrayList<>(set);

      Collections.sort(list);

      return list;
    });
  }

  public void runTest(List<KeyExtent> loadRanges, List<KeyExtent> tabletRanges) throws Exception {
    TabletIterFactory tabletIterFactory = startRow -> {
      int start = -1;

      if (startRow == null) {
        start = 0;
      } else {
        for (int i = 0; i < tabletRanges.size(); i++) {
          if (tabletRanges.get(i).contains(startRow)) {
            start = i;
            break;
          }
        }
      }

      return tabletRanges.subList(start, tabletRanges.size()).iterator();
    };

    PrepBulkImport.checkForMerge("1", loadRanges.iterator(), tabletIterFactory);
  }

  static String toRangeStrings(Collection<KeyExtent> extents) {
    return extents.stream().map(ke -> "(" + ke.getPrevEndRow() + "," + ke.getEndRow() + "]")
        .collect(Collectors.joining(","));
  }

  public void runExceptionTest(List<KeyExtent> loadRanges, List<KeyExtent> tabletRanges)
      throws AccumuloException {
    try {
      runTest(loadRanges, tabletRanges);
      fail("expected " + toRangeStrings(loadRanges) + " to fail against "
          + toRangeStrings(tabletRanges));
    } catch (Exception e) {
      assertTrue(e instanceof AcceptableThriftTableOperationException);
    }
  }

  @Test
  public void testSingleTablet() throws Exception {
    runTest(Arrays.asList(nke(null, null)), Arrays.asList(nke(null, null)));

    for (List<KeyExtent> loadRanges : powerSet(nke(null, "b"), nke("b", "k"), nke("k", "r"),
        nke("r", null))) {
      if (loadRanges.isEmpty()) {
        continue;
      }
      runExceptionTest(loadRanges, Arrays.asList(nke(null, null)));
    }
  }

  @Test
  public void testNominal() throws Exception {

    for (List<KeyExtent> loadRanges : powerSet(nke(null, "b"), nke("b", "m"), nke("m", "r"),
        nke("r", "v"), nke("v", null))) {

      if (loadRanges.isEmpty()) {
        loadRanges = Arrays.asList(nke(null, null));
      }

      List<String> requiredRows = Arrays.asList("b", "m", "r", "v");
      for (Set<String> otherRows : Sets.powerSet(Set.of("a", "c", "q", "t", "x"))) {
        runTest(loadRanges, createExtents(Iterables.concat(requiredRows, otherRows)));
      }
    }
  }

  @Test
  public void testException() throws Exception {
    for (List<KeyExtent> loadRanges : powerSet(nke(null, "b"), nke("b", "m"), nke("m", "r"),
        nke("r", "v"), nke("v", null))) {

      if (loadRanges.isEmpty()) {
        continue;
      }

      Set<String> rows = new HashSet<>();
      for (KeyExtent ke : loadRanges) {
        if (ke.getPrevEndRow() != null) {
          rows.add(ke.getPrevEndRow().toString());
        }
        if (ke.getEndRow() != null) {
          rows.add(ke.getEndRow().toString());
        }
      }

      for (String row : rows) {
        Set<String> rows2 = new HashSet<>(rows);
        rows2.remove(row);
        // test will all but one of the rows in the load mapping
        for (Set<String> otherRows : Sets.powerSet(Set.of("a", "c", "q", "t", "x"))) {
          runExceptionTest(loadRanges, createExtents(Iterables.concat(rows2, otherRows)));
        }
      }

      if (rows.size() > 1) {
        // test with none of the rows in the load mapping
        for (Set<String> otherRows : Sets.powerSet(Set.of("a", "c", "q", "t", "x"))) {
          runExceptionTest(loadRanges, createExtents(otherRows));
        }
      }
    }

  }
}
