/*******************************************************************************
 * Copyright (c) 2019 École Polytechnique de Montréal
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package org.eclipse.tracecompass.incubator.callstack.core.tests.callgraph;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.AllGroupDescriptor;
import org.eclipse.tracecompass.incubator.callstack.core.tests.flamechart.CallStackTestBase;
import org.eclipse.tracecompass.incubator.callstack.core.tests.stubs.CallStackAnalysisStub;
import org.eclipse.tracecompass.incubator.callstack.core.tests.stubs.FlameDataProviderTestUtils;
import org.eclipse.tracecompass.incubator.internal.callstack.core.flamegraph.FlameGraphDataProvider;
import org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.provider.FlameChartEntryModel;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphRowModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphState;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphModel;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;

/**
 * Test the {@link FlameGraphDataProvider} class
 *
 * @author Geneviève Bastien
 */
public class FlameGraphDataProviderTest extends CallStackTestBase {

    private static final String EXPECTED_FILE_PATH = "testfiles/dp/";

    private static final @NonNull Map<@NonNull String, @NonNull Object> TREE_PARAMETERS = ImmutableMap.of(
            DataProviderParameterUtils.REQUESTED_TIME_KEY, ImmutableList.of(0, Long.MAX_VALUE));

    /**
     * Test the {@link FlameGraphDataProvider} for the test callstack, with all
     * items separately
     *
     * @throws IOException
     *             if an I/O error occurs reading from the expected value file
     *             or a malformed or unmappable byte sequence is read
     */
    @Test
    public void testFlameGraphDataProviderAllItems() throws IOException {
        CallStackAnalysisStub cga = getModule();

        FlameGraphDataProvider<?, ?, ?> provider = new FlameGraphDataProvider<>(getTrace(), cga, cga.getId());

        Map<Long, FlameChartEntryModel> idsToNames = assertAndGetTree(provider, "expectedFgTreeFull", Collections.emptyMap());

        assertRowsRequests(provider, idsToNames, "Full", 19);
    }

    /**
     * Test the {@link FlameGraphDataProvider} for the test callstack, with
     * items grouped by process
     *
     * @throws IOException
     *             if an I/O error occurs reading from the expected value file
     *             or a malformed or unmappable byte sequence is read
     */
    @Test
    public void testFlameGraphDataProviderGroupByProcess() throws IOException {
        CallStackAnalysisStub cga = getModule();

        FlameGraphDataProvider<?, ?, ?> provider = new FlameGraphDataProvider<>(getTrace(), cga, cga.getId());

        Map<Long, FlameChartEntryModel> idsToNames = assertAndGetTree(provider, "expectedFgTreeProcess", ImmutableMap.of(FlameGraphDataProvider.GROUP_BY_KEY, "Processes/*"));

        assertRowsRequests(provider, idsToNames, "Process", 38);

    }

    /**
     * Test the {@link FlameGraphDataProvider} for the test callstack, with all
     * items grouped together.
     *
     * @throws IOException
     *             if an I/O error occurs reading from the expected value file
     *             or a malformed or unmappable byte sequence is read
     */
    @Test
    public void testFlameGraphDataProviderGrouped() throws IOException {
        CallStackAnalysisStub cga = getModule();

        FlameGraphDataProvider<?, ?, ?> provider = new FlameGraphDataProvider<>(getTrace(), cga, cga.getId());

        Map<Long, FlameChartEntryModel> idsToNames = assertAndGetTree(provider, "expectedFgTreeOne", ImmutableMap.of(FlameGraphDataProvider.GROUP_BY_KEY, AllGroupDescriptor.getInstance().getName()));

        assertRowsRequests(provider, idsToNames, "One", 72);

    }

    /**
     * Test the {@link FlameGraphDataProvider} for the test callstack, with only
     * the callgraph for a time selection.
     *
     * @throws IOException
     *             if an I/O error occurs reading from the expected value file
     *             or a malformed or unmappable byte sequence is read
     */
    @Test
    public void testFlameGraphDataProviderSelection() throws IOException {
        CallStackAnalysisStub cga = getModule();

        FlameGraphDataProvider<?, ?, ?> provider = new FlameGraphDataProvider<>(getTrace(), cga, cga.getId());

        Map<Long, FlameChartEntryModel> idsToNames = assertAndGetTree(provider, "expectedFgTreeSelection", ImmutableMap.of(FlameGraphDataProvider.SELECTION_RANGE_KEY, ImmutableList.of(5, 15)));

        assertRowsRequests(provider, idsToNames, "Selection", 10);

    }

    private static void assertRowsRequests(FlameGraphDataProvider<?, ?, ?> provider, Map<Long, FlameChartEntryModel> idsToNames, String resultFileSuffix, long maxDuration) throws IOException {
        String filePrefix = "expectedFgRow" + resultFileSuffix;
        // Test getting all the states
        Builder<Long> builder = ImmutableList.builder();
        for (long i = 0; i < maxDuration; i++) {
            builder.add(i);
        }
        assertRows(provider, idsToNames, builder.build(), filePrefix, "All");

        // Test getting only the first and last states
        assertRows(provider, idsToNames, ImmutableList.of(0L, maxDuration - 1), filePrefix, "2Times");

        // Test getting the states for the last half of the flamegraph
        builder = ImmutableList.builder();
        for (long i = maxDuration / 2; i < maxDuration; i++) {
            builder.add(i);
        }
        assertRows(provider, idsToNames, builder.build(), filePrefix, "Zoom");
    }

    private static Map<Long, FlameChartEntryModel> assertAndGetTree(FlameGraphDataProvider<?, ?, ?> provider, String filePath, @NonNull Map<@NonNull String, @NonNull Object> additionalParameters) throws IOException {
        Map<@NonNull String, @NonNull Object> parameters = new HashMap<>(TREE_PARAMETERS);
        parameters.putAll(additionalParameters);
        TmfModelResponse<TmfTreeModel<@NonNull FlameChartEntryModel>> treeResponse = provider.fetchTree(parameters, null);
        assertNotNull(treeResponse);
        assertEquals(ITmfResponse.Status.COMPLETED, treeResponse.getStatus());
        TmfTreeModel<@NonNull FlameChartEntryModel> treeModel = treeResponse.getModel();
        assertNotNull(treeModel);
        List<@NonNull FlameChartEntryModel> treeEntries = treeModel.getEntries();

        List<String> expectedStrings = Files.readAllLines(Paths.get(EXPECTED_FILE_PATH + filePath));
        assertEquals(expectedStrings.size(), treeEntries.size());
        for (int i = 0; i < expectedStrings.size(); i++) {
            String expectedString = expectedStrings.get(i);
            String[] split = expectedString.split(",");

            FlameChartEntryModel parent = null;
            if (!split[5].equals("-")) {
                parent = FlameDataProviderTestUtils.findEntryByNameAndType(treeEntries, split[5], getEntryType(split[4]));
                assertNotNull("parent entry of " + split[0] + ' ' + split[1] + " with parent " + split[5], parent);
            }

            // Find the entry with type and name with the parent entry, since
            // function entries have similar name, look with the parent
            FlameChartEntryModel fgEntry = parent == null ? FlameDataProviderTestUtils.findEntryByNameAndType(treeEntries, split[1], getEntryType(split[0]))
                    : FlameDataProviderTestUtils.findEntryByNameAndType(FlameDataProviderTestUtils.findEntriesByParent(treeEntries, parent.getId()), split[1], getEntryType(split[0]));
            assertNotNull("Expecting entry " + split[0] + ' ' + split[1] + " with parent " + split[5], fgEntry);
            assertEquals("Start time of entry " + split[0] + ' ' + split[1] + " with parent " + split[5], Long.parseLong(split[2]), fgEntry.getStartTime());
            assertEquals("End time of entry " + split[0] + ' ' + split[1] + " with parent " + split[5], Long.parseLong(split[3]), fgEntry.getEndTime());
            assertEquals("Parent ID of entry " + split[0] + ' ' + split[1] + " with parent " + split[5], parent == null ? -1 : parent.getId(), fgEntry.getParentId());

        }
        Map<Long, FlameChartEntryModel> map = new HashMap<>();
        for (FlameChartEntryModel fgModel : treeEntries) {
            map.put(fgModel.getId(), fgModel);
        }
        return map;
    }

    private static FlameChartEntryModel.EntryType getEntryType(String string) {
        return FlameChartEntryModel.EntryType.valueOf(string.toUpperCase());
    }

    private static void assertRows(FlameGraphDataProvider<?, ?, ?> provider, Map<Long, FlameChartEntryModel> idsToNames, @NonNull List<Long> requestedTimes, String filePath, String descriptor) throws IOException {
        TmfModelResponse<TimeGraphModel> rowResponse = provider.fetchRowModel(prepareRowParameters(idsToNames.keySet(), requestedTimes), null);
        assertNotNull(rowResponse);
        assertEquals(ITmfResponse.Status.COMPLETED, rowResponse.getStatus());
        TimeGraphModel rowModel = rowResponse.getModel();
        assertNotNull(rowModel);
        Map<Long, @NonNull ITimeGraphRowModel> rows = new HashMap<>();
        for (ITimeGraphRowModel oneRow : rowModel.getRows()) {
            rows.put(oneRow.getEntryID(), oneRow);
        }
        // ensure row order
        Collection<FlameChartEntryModel> models = idsToNames.values();

        List<String> expectedStrings = Files.readAllLines(Paths.get(EXPECTED_FILE_PATH + filePath + descriptor));
        assertEquals(expectedStrings.size(), rows.size());
        for (int i = 0; i < expectedStrings.size(); i++) {
            String expectedString = expectedStrings.get(i);
            String[] split = expectedString.split(":");
            FlameChartEntryModel fgEntry = findRowEntry(split[0], models);
            assertNotNull(descriptor + ":Entry exists " + split[0], fgEntry);

            ITimeGraphRowModel row = rows.get(fgEntry.getId());
            assertNotNull(descriptor + ": Row entry exists" + split[0], row);

            assertEqualsStates(split[1], row.getStates(), descriptor + ": " + split[0]);
        }
    }

    private static FlameChartEntryModel findRowEntry(String entryDetails, Collection<FlameChartEntryModel> models) {
        String[] details = entryDetails.split(",");
        FlameChartEntryModel parentEntry = FlameDataProviderTestUtils.findEntryByNameAndType(models, details[3], getEntryType(details[2]));
        if (parentEntry == null) {
            return null;
        }
        return FlameDataProviderTestUtils.findEntryByNameAndType(FlameDataProviderTestUtils.findEntriesByParent(models, parentEntry.getId()), details[1], getEntryType(details[0]));
    }

    private static @NonNull Map<@NonNull String, @NonNull Object> prepareRowParameters(@NonNull Set<Long> ids, @NonNull List<Long> requestedTimes) {
        return ImmutableMap.of(DataProviderParameterUtils.REQUESTED_TIME_KEY, requestedTimes, DataProviderParameterUtils.REQUESTED_ITEMS_KEY, ids);
    }

    private static void assertEqualsStates(String string, @NonNull List<@NonNull ITimeGraphState> states, String descriptor) {
        String[] stringStates = string.split(",");
        for (int i = 0; i < stringStates.length / 4; i++) {
            assertTrue(descriptor + " has state " + i, states.size() > i);
            ITimeGraphState state = states.get(i);
            assertEquals(descriptor + ": start time at position " + i, Long.parseLong(stringStates[i * 4]), state.getStartTime());
            assertEquals(descriptor + ": duration at position " + i, Long.parseLong(stringStates[i * 4 + 1]), state.getDuration());
            String strValue = stringStates[i * 4 + 2];
            assertEquals(descriptor + ": value at position " + i, strValue.equals("-") ? Integer.MIN_VALUE : Objects.hash(strValue), state.getValue());
            assertEquals(descriptor + ": label at position " + i, stringStates[i * 4 + 3], String.valueOf(state.getLabel()));
        }
        assertEquals(descriptor + " no extra state", stringStates.length / 4, states.size());
    }

}
