/*******************************************************************************
 * Copyright (c) 2018, 2020 Ericsson and others
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License 2.0 which
 * accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/

package org.eclipse.tracecompass.incubator.internal.kernel.core.fileaccess;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.analysis.core.model.ModelManager;
import org.eclipse.tracecompass.incubator.internal.kernel.core.Activator;
import org.eclipse.tracecompass.incubator.internal.kernel.core.fileaccess.FileEntryModel.Type;
import org.eclipse.tracecompass.incubator.internal.kernel.core.filedescriptor.FileDescriptorStateProvider;
import org.eclipse.tracecompass.incubator.internal.kernel.core.filedescriptor.ThreadEntryModel;
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
import org.eclipse.tracecompass.internal.tmf.core.model.timegraph.AbstractTimeGraphDataProvider;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
import org.eclipse.tracecompass.tmf.core.dataprovider.X11ColorUtils;
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
import org.eclipse.tracecompass.tmf.core.model.IOutputStyleProvider;
import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
import org.eclipse.tracecompass.tmf.core.model.OutputStyleModel;
import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
import org.eclipse.tracecompass.tmf.core.model.filters.SelectionTimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphArrow;
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.TimeGraphEntryModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphRowModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphState;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse.Status;
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;

/**
 * <p>
 * File Descriptor data Provider
 * </p>
 * <p>
 * Shows per-file access
 * </p>
 *
 * @author Matthew Khouzam
 */
@SuppressWarnings("restriction")
public class FileAccessDataProvider extends AbstractTimeGraphDataProvider<@NonNull FileAccessAnalysis, @NonNull TimeGraphEntryModel>
        implements IOutputStyleProvider {

    /**
     * Suffix for dataprovider ID
     */
    public static final String SUFFIX = ".dataprovider"; //$NON-NLS-1$ ;
    /**
     * String for the tid parameter of this view
     */
    public static final String TID_PARAM = "tid"; //$NON-NLS-1$

    private static final Pattern IS_INTEGER = Pattern.compile("\\d+"); //$NON-NLS-1$

    private static final String META_IO_NAME = "Meta IO"; //$NON-NLS-1$
    private static final String IO_NAME = "IO"; //$NON-NLS-1$

    /* The map of basic styles */
    private static final Map<String, OutputElementStyle> STATE_MAP;
    /*
     * A map of styles names to a style that has the basic style as parent, to
     * avoid returning complete styles for each state
     */
    private static final Map<String, OutputElementStyle> STYLE_MAP = new HashMap<>();

    static {
        /* Build three different styles to use as examples */
        ImmutableMap.Builder<String, OutputElementStyle> builder = new ImmutableMap.Builder<>();

        builder.put(META_IO_NAME, new OutputElementStyle(null, ImmutableMap.of(StyleProperties.STYLE_NAME, META_IO_NAME,
                StyleProperties.BACKGROUND_COLOR, String.valueOf(X11ColorUtils.toHexColor(174, 123, 131)))));
        builder.put(IO_NAME, new OutputElementStyle(null, ImmutableMap.of(StyleProperties.STYLE_NAME, IO_NAME,
                StyleProperties.BACKGROUND_COLOR, String.valueOf(X11ColorUtils.toHexColor(140, 180, 165)))));
        STATE_MAP = builder.build();
    }

    private static final int OFFSET = 100000;
    private static final AtomicInteger STRING_VALUE = new AtomicInteger(OFFSET);
    private Map<String, Integer> fileIds = new HashMap<>();

    /**
     * Constructor
     *
     * @param trace
     *            the trace this provider represents
     * @param analysisModule
     *            the analysis encapsulated by this provider
     */
    public FileAccessDataProvider(ITmfTrace trace, FileAccessAnalysis analysisModule) {
        super(trace, analysisModule);
    }

    @Deprecated
    @Override
    public @NonNull TmfModelResponse<@NonNull List<@NonNull ITimeGraphArrow>> fetchArrows(@NonNull TimeQueryFilter filter, @Nullable IProgressMonitor monitor) {
        Map<String, Object> parameters = FetchParametersUtils.timeQueryToMap(filter);
        return fetchArrows(parameters, monitor);
    }

    @Override
    public TmfModelResponse<List<ITimeGraphArrow>> fetchArrows(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        return new TmfModelResponse<>(null, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
    }

    @Override
    public @NonNull String getId() {
        return getAnalysisModule().getId() + SUFFIX;
    }

    @Override
    protected @Nullable TimeGraphModel getRowModel(ITmfStateSystem ss, Map<String, Object> parameters, @Nullable IProgressMonitor monitor) throws StateSystemDisposedException {
        SelectionTimeQueryFilter filter = FetchParametersUtils.createSelectionTimeQuery(parameters);
        if (filter == null) {
            return null;
        }
        TreeMultimap<Integer, ITmfStateInterval> intervals = TreeMultimap.create(Comparator.naturalOrder(),
                Comparator.comparing(ITmfStateInterval::getStartTime));
        Map<@NonNull Long, @NonNull Integer> entries = getSelectedEntries(filter);
        Collection<Long> times = getTimes(filter, ss.getStartTime(), ss.getCurrentEndTime());
        /* Do the actual query */
        for (ITmfStateInterval interval : ss.query2D(entries.values(), times)) {
            if (monitor != null && monitor.isCanceled()) {
                return new TimeGraphModel(Collections.emptyList());
            }
            intervals.put(interval.getAttribute(), interval);
        }
        Map<@NonNull Integer, @NonNull Predicate<@NonNull Multimap<@NonNull String, @NonNull Object>>> predicates = new HashMap<>();
        Multimap<@NonNull Integer, @NonNull String> regexesMap = DataProviderParameterUtils.extractRegexFilter(parameters);
        if (regexesMap != null) {
            predicates.putAll(computeRegexPredicate(regexesMap));
        }
        List<@NonNull ITimeGraphRowModel> rows = new ArrayList<>();
        for (Map.Entry<@NonNull Long, @NonNull Integer> entry : entries.entrySet()) {
            if (monitor != null && monitor.isCanceled()) {
                return new TimeGraphModel(Collections.emptyList());
            }

            List<ITimeGraphState> eventList = new ArrayList<>();
            for (ITmfStateInterval interval : intervals.get(entry.getValue())) {
                long startTime = interval.getStartTime();
                long duration = interval.getEndTime() - startTime + 1;
                Object state = interval.getValue();
                String label = null;
                TimeGraphState value = null;
                if (Integer.valueOf(1).equals(state)) {
                    ITmfTrace trace = getTrace();
                    List<Integer> sub = ss.getSubAttributes(interval.getAttribute(), false);
                    for (ITmfStateInterval threadInterval : ss.query2D(sub, Collections.singleton(startTime))) {
                        Object sv = threadInterval.getValue();
                        if (sv != null) {
                            int tid = getTid(ss, threadInterval.getAttribute());
                            label = getThreadName(tid, interval.getStartTime(), trace) + " (" + tid + ")"; //$NON-NLS-1$ //$NON-NLS-2$
                            value = new TimeGraphState(startTime, duration, label,
                                    STYLE_MAP.computeIfAbsent(META_IO_NAME, n -> new OutputElementStyle(n)));
                            break;
                        }
                    }
                }
                if (state != null && value == null) {
                    value = new TimeGraphState(startTime, duration, null, STYLE_MAP.computeIfAbsent(IO_NAME, n -> new OutputElementStyle(n)));
                }
                if (value == null) {
                    value = new TimeGraphState(startTime, duration, Integer.MIN_VALUE);
                }
                applyFilterAndAddState(eventList, value, entry.getKey(), predicates, monitor);
            }
            rows.add(new TimeGraphRowModel(entry.getKey(), eventList));

        }
        return new TimeGraphModel(rows);
    }

    @Override
    protected boolean isCacheable() {
        return false;
    }

    @Deprecated
    @Override
    public TmfModelResponse<Map<String, String>> fetchTooltip(SelectionTimeQueryFilter filter, @Nullable IProgressMonitor monitor) {
        Map<String, Object> parameters = FetchParametersUtils.selectionTimeQueryToMap(filter);
        return fetchTooltip(parameters, monitor);
    }

    @Override
    public TmfModelResponse<Map<String, String>> fetchTooltip(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        ITmfStateSystem ss = getAnalysisModule().getStateSystem();
        SelectionTimeQueryFilter filter = FetchParametersUtils.createSelectionTimeQuery(fetchParameters);
        if (filter == null) {
            return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, CommonStatusMessage.INCORRECT_QUERY_PARAMETERS);
        }
        Collection<@NonNull Integer> quarks = getSelectedEntries(filter).values();
        Map<String, String> retMap = new LinkedHashMap<>();

        if (quarks.size() != 1) {
            return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
        }

        long start = filter.getStart();
        if (ss == null || quarks.size() != 1 || !getAnalysisModule().isQueryable(start)) {
            /*
             * We need the ss to query, we should only be querying one attribute
             * and the query times should be valid.
             */
            return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
        }
        int quark = quarks.iterator().next();
        try {
            ITmfStateInterval current = ss.querySingleState(start, quark);

            int resQuark = ss.optQuarkAbsolute(FileDescriptorStateProvider.RESOURCES);
            if (resQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
                return new TmfModelResponse<>(retMap, ITmfResponse.Status.FAILED, "Bizarre quark value for the file resources"); //$NON-NLS-1$
            }
            int parentQuark = ss.getParentAttributeQuark(quark);
            if (parentQuark == resQuark) {
                // This is a file name, add the number of opened fd and full
                // file name
                String fileName = ss.getAttributeName(quark);
                retMap.put("File Name", fileName); //$NON-NLS-1$
                Object value = current.getValue();
                retMap.put("Number of opened FD", (value instanceof Number) ? String.valueOf(value) : "0"); //$NON-NLS-1$ //$NON-NLS-2$
                return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
            }

            int parentQuark2 = ss.getParentAttributeQuark(parentQuark);
            if (parentQuark2 == resQuark) {
                // This is a thread, add the fd and full file name
                String fileName = ss.getAttributeName(parentQuark);
                retMap.put("File Name", fileName); //$NON-NLS-1$
                Object value = current.getValue();
                if (value instanceof Number) {
                    retMap.put("FD", String.valueOf(value)); //$NON-NLS-1$
                }
                return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
            }

            // Not something we know what to do

            return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
        } catch (StateSystemDisposedException e) {
            // Ignore, nothing to do
        }

        return new TmfModelResponse<>(null, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
    }

    @Override
    protected TmfTreeModel<TimeGraphEntryModel> getTree(ITmfStateSystem ss, Map<String, Object> parameters, @Nullable IProgressMonitor monitor) throws StateSystemDisposedException {

        Object tidParam = parameters.get(TID_PARAM);
        Integer selectedTids = (tidParam instanceof Integer) ? (Integer) tidParam : -1;

        Builder<@NonNull TimeGraphEntryModel> builder = new Builder<>();
        long rootId = getId(ITmfStateSystem.ROOT_ATTRIBUTE);
        ITmfTrace trace = getTrace();
        builder.add(new TimeGraphEntryModel(rootId, -1, String.valueOf(trace.getName()), ss.getStartTime(), ss.getCurrentEndTime()));
        try {
            addResources(ss, builder, ss.getQuarkAbsolute(FileDescriptorStateProvider.RESOURCES), rootId, selectedTids);
        } catch (AttributeNotFoundException e) {
            Activator.getInstance().logError(e.getMessage(), e);
        }

        return new TmfTreeModel<>(Collections.emptyList(), builder.build());
    }

    private void addResources(ITmfStateSystem ss, Builder<@NonNull TimeGraphEntryModel> builder, int quark, long parentId, Integer filter) {
        List<@NonNull Integer> fileQuarks = ss.getSubAttributes(quark, false);

        String ramFiles = "in memory"; //$NON-NLS-1$
        boolean hasMemfile = false;
        int ramHash = fileIds.computeIfAbsent(ramFiles, a -> STRING_VALUE.incrementAndGet());
        long ramId = getId(ramHash);
        TimeGraphEntryModel ramElement = new TimeGraphEntryModel(ramId, parentId, ramFiles, ss.getStartTime(), ss.getCurrentEndTime());

        for (Integer fileQuark : fileQuarks) {
            String name = ss.getAttributeName(fileQuark);
            long id = getId(fileQuark);
            List<Integer> sub = ss.getSubAttributes(fileQuark, false);
            Set<Integer> contributingTids = sub.stream()
                    .map(ss::getAttributeName)
                    .filter(FileAccessDataProvider::isInteger)
                    .map(Integer::parseInt)
                    .collect(Collectors.toSet());
            if (filter == -1 || contributingTids.contains(filter)) {
                if (name.startsWith(File.separator)) {
                    String[] segments = name.split(File.separator);
                    StringBuilder sb = new StringBuilder();
                    long parent = parentId;
                    builder.add(new FileEntryModel(getId(fileIds.computeIfAbsent(File.separator, a -> STRING_VALUE.incrementAndGet())), parentId, File.separator, ss.getStartTime(), ss.getCurrentEndTime(), false, Type.Directory));
                    for (int i = 0; i < segments.length - 1; i++) {
                        sb.append('/').append(segments[i]);
                        String fileName = sb.toString();
                        Long fileId = getId(fileIds.computeIfAbsent(fileName, a -> STRING_VALUE.incrementAndGet()));
                        builder.add(new FileEntryModel(fileId, parent, segments[i] + File.separator, ss.getStartTime(), ss.getCurrentEndTime(), false, Type.Directory));
                        parent = fileId;
                    }
                    builder.add(new FileEntryModel(id, parent, name.substring(1 + name.lastIndexOf(File.separator)), ss.getStartTime(), ss.getCurrentEndTime(), true, Type.File));

                } else {
                    if (!hasMemfile) {
                        builder.add(ramElement);
                        hasMemfile = true;
                    }
                    builder.add(new FileEntryModel(id, ramId, name, ss.getStartTime(), ss.getCurrentEndTime(), true, FileEntryModel.Type.InRam));
                }
                List<@NonNull Integer> threadQuarks = ss.getSubAttributes(fileQuark, false);
                if (threadQuarks.size() == 1) {
                    continue;
                }
                for (Integer threadQuark : threadQuarks) {
                    ITmfTrace trace = getTrace();
                    // Broken
                    int tid = getTid(ss, threadQuark);
                    if (tid != -1) {
                        String threadName = getThreadName(tid, ss.getStartTime(), trace);
                        builder.add(new ThreadEntryModel(getId(threadQuark), id, String.valueOf(threadName), ss.getStartTime(), ss.getCurrentEndTime(), true, tid));
                    }
                }
            }
        }
    }

    private static @Nullable String getThreadName(int tid, long time, ITmfTrace trace) {
        if (tid != -1) {
            return ModelManager.getModelFor(trace.getHostId()).getExecName(tid, time);
        }
        return null;
    }

    private static int getTid(ITmfStateSystem ss, int threadQuark) {
        String attributeName = ss.getAttributeName(threadQuark);
        if (isInteger(attributeName)) {
            return Integer.parseInt(attributeName);
        }
        return -1;
    }

    private static boolean isInteger(String attributeName) {
        return IS_INTEGER.matcher(attributeName).matches();
    }

    public @Nullable Long getBytesRead(long start, long end, long attributeId) {
        ITmfStateSystem ss = getAnalysisModule().getStateSystem();
        if (ss == null) {
            return null;
        }

        Map<Long, Integer> selectedEntries = getSelectedEntries(new SelectionTimeQueryFilter(Arrays.asList(start, end), Collections.singleton(attributeId)));
        Integer startingNodeQuark = selectedEntries.get(attributeId);
        if (startingNodeQuark == null || startingNodeQuark >= OFFSET) {
            return null;
        }
        int readQuark = ss.optQuarkRelative(startingNodeQuark, FileDescriptorStateProvider.READ);
        return getdelta(start, end, ss, readQuark);
    }

    public @Nullable Long getBytesWrite(long start, long end, long attributeId) {
        ITmfStateSystem ss = getAnalysisModule().getStateSystem();
        if (ss == null) {
            return null;
        }

        Map<Long, Integer> selectedEntries = getSelectedEntries(new SelectionTimeQueryFilter(Arrays.asList(start, end), Collections.singleton(attributeId)));
        Integer startingNodeQuark = selectedEntries.get(attributeId);
        if (startingNodeQuark == null || startingNodeQuark >= OFFSET) {
            return null;
        }
        int readQuark = ss.optQuarkRelative(startingNodeQuark, FileDescriptorStateProvider.WRITE);
        return getdelta(start, end, ss, readQuark);
    }

    private static @Nullable Long getdelta(long start, long end, ITmfStateSystem ss, int readQuark) {
        if (readQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
            return null;
        }
        try {
            ITmfStateInterval startInterval = ss.querySingleState(start, readQuark);
            ITmfStateInterval endInterval = ss.querySingleState(end, readQuark);
            return endInterval.getValueLong() - startInterval.getValueLong();
        } catch (StateSystemDisposedException e) {
            return null;
        }
    }

    @Override
    public @NonNull Multimap<@NonNull String, @NonNull Object> getFilterData(long entryId, long time, @Nullable IProgressMonitor monitor) {
        Multimap<@NonNull String, @NonNull Object> data = HashMultimap.create();
        data.putAll(super.getFilterData(entryId, time, monitor));

        SelectionTimeQueryFilter filter = new SelectionTimeQueryFilter(Collections.singletonList(time), Collections.singleton(Objects.requireNonNull(entryId)));
        TmfModelResponse<Map<String, String>> response = fetchTooltip(filter, monitor);
        Map<@NonNull String, @NonNull String> model = response.getModel();
        if (model != null) {
            for (Entry<String, String> entry : model.entrySet()) {
                data.put(entry.getKey(), entry.getValue());
            }
        }
        return data;
    }

    @Override
    public TmfModelResponse<OutputStyleModel> fetchStyle(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        return new TmfModelResponse<>(new OutputStyleModel(STATE_MAP), Status.COMPLETED, CommonStatusMessage.COMPLETED);
    }

}
