package com.criteo.biggraphite.graphiteindex;

import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

/**
 * Tests queries against an in-memory metrics index.
 * Offset values are generated using the path's hashCode.
 */
@RunWith(Parameterized.class)
public class MetricsIndexQueriesTest {
    private static Set<String> setOf(String... xs) {
        return new HashSet<>(Arrays.asList(xs));
    }

    public static final Object[][] testQueries = {
        {
            "a.single.metric",
            setOf(
                "a.single.metric"
            ),
        },
        {
            "a.few.metrics.*",
            setOf(
                "a.few.metrics.a",
                "a.few.metrics.b",
                "a.few.metrics.c"
            ),
        },
        {
            "lots.of.wildcards.*****",
            setOf(
                "lots.of.wildcards.a",
                "lots.of.wildcards.b",
                "lots.of.wildcards.c"
            ),
        },
        {
            "metrics.match{ed_by,ing}.s[ao]me.regexp.?[0-9]",
            setOf(
                "metrics.matched_by.same.regexp.b2",
                "metrics.matched_by.some.regexp.a1",
                "metrics.matching.same.regexp.w5",
                "metrics.matching.some.regexp.z8"
            ),
        },
    };

    public static final String[] unmatchedMetricNames = {
        "a.single.metric.two",

        "a.few.metrcs.a",
        "a.few.metrocs.z",

        "lots.at.wildcard.a",
        "lots.of.wildchord.b",

        "metrics.matxing.some.regexp.a1",
        "metrics.matchacha.same.regexp.z5"
    };

    public static MetricsIndex index;

    @BeforeClass
    @SuppressWarnings("unchecked")
    public static void buildTestIndex() throws IOException {
        index = new MetricsIndex("test-index");

        for (Object[] testQuery : testQueries) {
            Set<String> metricNames = (Set<String>)testQuery[1];
            for (String metricName : metricNames) {
                index.insert(metricName, (long)metricName.hashCode());
            }
        }

        for (String metricName : unmatchedMetricNames) {
            index.insert(metricName, (long)metricName.hashCode());
        }

        index.forceCommit();
    }

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(testQueries);
    }

    @Parameter(0)
    public String query;

    @Parameter(1)
    public Set<String> expectedResults;

    @Test
    public void shouldReturnCorrectSearchResults() {
        List<Pair<String, Long>> results = index.searchPaths(query);
        Set<String> uniquePaths = results
            .stream()
            .map(Pair::getLeft)
            .collect(Collectors.toSet());

        assertEquals(expectedResults, uniquePaths);
    }

    @Test
    public void shouldStoreAndRetrieveOffsetValues() {
        for (Pair<String, Long> entry : index.searchPaths(query)) {
            assertEquals((long)entry.getLeft().hashCode(), entry.getRight().longValue());
        }
    }
}

@@ -1219,218 +1219,8 @@
   %7B%0A
-            %22lots.of.wildcards.*****%22,%0A            setOf(%0A                %22lots.of.wildcards.a%22,%0A                %22lots.of.wildcards.b%22,%0A                %22lots.of.wildcards.c%22%0A            ),%0A        %7D,%0A        %7B%0A
     
@@ -1685,70 +1685,8 @@
 %22,%0A%0A
-        %22lots.at.wildcard.a%22,%0A        %22lots.of.wildchord.b%22,%0A%0A
     

drop "lots of wildcards" test case