/**********************************************************************
 * Copyright (c) 2017 Ericsson
 *
 * 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.internal.tmf.analysis.xml.core.module;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
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.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Messages;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.compile.AnalysisCompilationData;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.compile.TmfXmlStateSystemPathCu;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.fsm.model.DataDrivenStateSystemPath;
import org.eclipse.tracecompass.internal.tmf.core.model.AbstractTmfTraceDataProvider;
import org.eclipse.tracecompass.internal.tmf.core.model.TmfXyResponseFactory;
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlStrings;
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlUtils;
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
import org.eclipse.tracecompass.tmf.core.model.YModel;
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.tree.ITmfTreeDataModel;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeDataModel;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel;
import org.eclipse.tracecompass.tmf.core.model.xy.ITmfTreeXYDataProvider;
import org.eclipse.tracecompass.tmf.core.model.xy.ITmfXyModel;
import org.eclipse.tracecompass.tmf.core.model.xy.IYModel;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.w3c.dom.Element;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;

/**
 * This data provider will return a XY model (wrapped in a response) based on a
 * query filter. The model can be used afterwards by any viewer to draw charts.
 * Model returned is for XML analysis
 *
 * @author Yonni Chen
 * @since 2.3
 */
@NonNullByDefault
public class XmlXYDataProvider extends AbstractTmfTraceDataProvider
        implements ITmfTreeXYDataProvider<ITmfTreeDataModel> {

    private static final String TITLE = Objects.requireNonNull(Messages.XmlDataProvider_DefaultXYTitle);
    /**
     * Data provider ID
     */
    public static final String ID = "org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlXYDataProvider"; //$NON-NLS-1$
    private static final String SPLIT_STRING = "/"; //$NON-NLS-1$
    private static final Pattern WILDCARD_PATTERN = Pattern.compile("\\*"); //$NON-NLS-1$
    private static final AtomicLong ENTRY_IDS = new AtomicLong();

    private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock(false);
    /**
     * Two way association between quarks and entry IDs, ensures that a single ID is
     * reused per every quark, and finds the quarks to query for the XY models.
     */
    private final BiMap<Long, Integer> fIdToQuark = HashBiMap.create();
    private final BiMap<Integer, String> fQuarkToString = HashBiMap.create();
    private final long fTraceId = ENTRY_IDS.getAndIncrement();
    private @Nullable TmfModelResponse<TmfTreeModel<ITmfTreeDataModel>> fCached;

    private static class XmlXYEntry implements IXmlStateSystemContainer {

        private final ITmfAnalysisModuleWithStateSystems fStateSystemModule;
        private final String fPath;
        private final DisplayType fType;
        private final AnalysisCompilationData fCompilationData;

        public XmlXYEntry(ITmfAnalysisModuleWithStateSystems stateSystem, String path, Element entryElement, AnalysisCompilationData compilationData) {
            fStateSystemModule = stateSystem;
            fPath = path;
            switch (entryElement.getAttribute(TmfXmlStrings.DISPLAY_TYPE)) {
            case TmfXmlStrings.DISPLAY_TYPE_DELTA:
                fType = DisplayType.DELTA;
                break;
            case TmfXmlStrings.DISPLAY_TYPE_ABSOLUTE:
            default:
                fType = DisplayType.ABSOLUTE;
                break;
            }
            fCompilationData = compilationData;
        }

        @Override
        public @Nullable String getAttributeValue(@Nullable String name) {
            // Method must be overridden
            return name;
        }

        @Override
        public ITmfStateSystem getStateSystem() {
            fStateSystemModule.waitForInitialization();
            Iterator<ITmfStateSystem> stateSystems = fStateSystemModule.getStateSystems().iterator();
            if (!stateSystems.hasNext()) {
                throw new NullPointerException("Analysis " + fStateSystemModule.getId() + " has no state system"); //$NON-NLS-1$ //$NON-NLS-2$
            }
            return stateSystems.next();
        }

        public DisplayType getType() {
            return fType;
        }

        public List<Integer> getQuarks() {
            /* This is an attribute tree path and not a file path */
            String[] paths = fPath.split(SPLIT_STRING);
            /* Get the list of quarks to process with this path */
            List<Integer> quarks = Collections.singletonList(IXmlStateSystemContainer.ROOT_QUARK);

            //recursively find the paths
            for (String path : paths) {
                List<Integer> subQuarks = new ArrayList<>();
                /* Replace * by .* to have a regex string */
                String name = WILDCARD_PATTERN.matcher(path).replaceAll(".*"); //$NON-NLS-1$
                for (int relativeQuark : quarks) {
                    subQuarks.addAll(getStateSystem().getSubAttributes(relativeQuark, false, name));
                }
                quarks = subQuarks;
            }
            return quarks;
        }

        @Override
        public @NonNull AnalysisCompilationData getAnalysisCompilationData() {
            return fCompilationData;
        }
    }

    private enum DisplayType {
        ABSOLUTE, DELTA
    }

    /** XML Model elements to use to create the series */
    private final DataDrivenStateSystemPath fDisplay;
    private final XmlXYEntry fXmlEntry;
    private final @Nullable DataDrivenStateSystemPath fSeriesNameAttrib;

    /**
     * Constructor
     */
    private XmlXYDataProvider(ITmfTrace trace, XmlXYEntry entry, DataDrivenStateSystemPath displayPath, @Nullable DataDrivenStateSystemPath seriesName) {
        super(trace);
        fXmlEntry = entry;
        fDisplay = displayPath;
        fSeriesNameAttrib = seriesName;
    }

    /**
     * Create an instance of {@link XmlXYDataProvider}. Returns null if statesystem
     * is null.
     *
     * @param trace
     *            A trace on which we are interested to fetch a model
     * @param analysisIds
     *            A list of analysis ids used for retrieving Analysis objects
     * @param entryElement
     *            An XML entry element
     * @return A XmlDataProvider
     */
    public static @Nullable XmlXYDataProvider create(ITmfTrace trace, Set<String> analysisIds, Element entryElement) {
        ITmfAnalysisModuleWithStateSystems ss = getStateSystemFromAnalyses(analysisIds, trace);
        if (ss == null) {
            return null;
        }
        AnalysisCompilationData compilationData = new AnalysisCompilationData();

        /*
         * Initialize state attributes. There should be only one entry element for XY
         * charts.
         */
        String path = entryElement.hasAttribute(TmfXmlStrings.PATH) ? entryElement.getAttribute(TmfXmlStrings.PATH) : TmfXmlStrings.WILDCARD;
        XmlXYEntry entry = new XmlXYEntry(ss, path, entryElement, compilationData);

        /* Get the display element to use */
        List<@NonNull Element> displayElements = TmfXmlUtils.getChildElements(entryElement, TmfXmlStrings.DISPLAY_ELEMENT);
        if (displayElements.isEmpty()) {
            return null;
        }
        Element displayElement = displayElements.get(0);
        TmfXmlStateSystemPathCu display = TmfXmlStateSystemPathCu.compile(entry.getAnalysisCompilationData(), Collections.singletonList(displayElement));
        if (display == null) {
            return null;
        }

        /* Get the series name element to use */
        List<Element> seriesNameElements = TmfXmlUtils.getChildElements(entryElement, TmfXmlStrings.NAME_ELEMENT);
        DataDrivenStateSystemPath seriesName = null;
        if (!seriesNameElements.isEmpty()) {
            Element seriesNameElement = seriesNameElements.get(0);
            TmfXmlStateSystemPathCu seriesNameCu = TmfXmlStateSystemPathCu.compile(entry.getAnalysisCompilationData(), Collections.singletonList(seriesNameElement));
            if (seriesNameCu != null) {
                seriesName = seriesNameCu.generate();
            }
        }

        return new XmlXYDataProvider(trace, entry, display.generate(), seriesName);

    }

    @Override
    public TmfModelResponse<ITmfXyModel> fetchXY(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        DataDrivenStateSystemPath display = fDisplay;
        XmlXYEntry entry = fXmlEntry;
        ITmfStateSystem ss = entry.getStateSystem();

        TimeQueryFilter filter = FetchParametersUtils.createTimeQuery(fetchParameters);
        if (filter == null) {
            return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.INCORRECT_QUERY_PARAMETERS);
        }
        long[] xValues = filter.getTimesRequested();
        Map<Integer, IYModel> map = initSeries(fetchParameters);
        if (map.isEmpty()) {
            return TmfXyResponseFactory.create(TITLE, xValues, Collections.emptyMap(), true);
        }

        long currentEnd = ss.getCurrentEndTime();

        try {
            for (int i = 0; i < xValues.length; i++) {
                if (monitor != null && monitor.isCanceled()) {
                    return TmfXyResponseFactory.createCancelledResponse(CommonStatusMessage.TASK_CANCELLED);
                }
                long time = xValues[i];
                if (time > currentEnd) {
                    break;
                } else if (ss.getStartTime() <= time) {
                    List<@NonNull ITmfStateInterval> full = ss.queryFullState(time);
                    for (Entry<Integer, IYModel> series : map.entrySet()) {
                        int attributeQuark = display.getQuark(series.getKey(), entry);
                        if (attributeQuark >= 0 && attributeQuark < full.size()) {
                            Object value = full.get(attributeQuark).getValue();
                            series.getValue().getData()[i] = extractValue(value);
                        }
                    }
                }
            }
            // Update the series value if delta is requested
            for (Entry<Integer, IYModel> series : map.entrySet()) {
                if (entry.getType().equals(DisplayType.DELTA)) {
                    getSeriesDelta(series.getValue().getData());
                }
            }
        } catch (StateSystemDisposedException e) {
            return TmfXyResponseFactory.createFailedResponse(e.getMessage());
        }

        boolean complete = ss.waitUntilBuilt(0) || filter.getEnd() <= currentEnd;
        return TmfXyResponseFactory.create(TITLE, xValues, Maps.uniqueIndex(map.values(), yModel -> Long.toString(yModel.getId())), complete);
    }

    private Map<Integer, IYModel> initSeries(Map<String, Object> parameters) {
        SelectionTimeQueryFilter filter = FetchParametersUtils.createSelectionTimeQuery(parameters);
        if (filter == null) {
            return Collections.emptyMap();
        }
        fLock.readLock().lock();
        try {
            Map<Integer, IYModel> map = new HashMap<>();
            int length = filter.getTimesRequested().length;
            for (Long id : filter.getSelectedItems()) {
                Integer quark = fIdToQuark.get(id);
                if (quark != null) {
                    String name = String.valueOf(fQuarkToString.get(quark));
                    map.put(quark, new YModel(id, name, new double[length]));
                }
            }
            return map;
        } finally {
            fLock.readLock().unlock();
        }
    }

    private static void getSeriesDelta(double[] data) {
        double prevData = data[0];
        data[0] = 0;
        for (int i = 1; i < data.length; i++) {
            double current = data[i];
            // Update value by subtracting previous value
            data[i] = current - prevData;
            prevData = current;
        }
        data[0] = data[1];
    }
    private static double extractValue(@Nullable Object val) {
        if (val instanceof Number) {
            return ((Number) val).doubleValue();
        }
        return 0;
    }

    private static @Nullable ITmfAnalysisModuleWithStateSystems getStateSystemFromAnalyses(Set<String> analysisIds, ITmfTrace trace) {
        @Nullable ITmfAnalysisModuleWithStateSystems stateSystemModule = null;
        if (analysisIds.isEmpty()) {
            stateSystemModule = Iterables.getFirst(TmfTraceUtils.getAnalysisModulesOfClass(trace, ITmfAnalysisModuleWithStateSystems.class), null);
        } else {
            for (String moduleId : analysisIds) {
                ITmfAnalysisModuleWithStateSystems module = TmfTraceUtils.getAnalysisModuleOfClass(trace, ITmfAnalysisModuleWithStateSystems.class, moduleId);
                if (module != null) {
                    stateSystemModule = module;
                    break;
                }
            }
        }

        if (stateSystemModule != null) {
            stateSystemModule.schedule();
        }
        return stateSystemModule;
    }

    /**
     * @since 2.4
     */
    @Override
    public TmfModelResponse<TmfTreeModel<ITmfTreeDataModel>> fetchTree(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        fLock.readLock().lock();
        try {
            if (fCached != null) {
                return fCached;
            }
        } finally {
            fLock.readLock().unlock();
        }

        ITmfStateSystem ss = fXmlEntry.getStateSystem();
        DataDrivenStateSystemPath seriesNameAttrib = fSeriesNameAttrib;

        boolean isComplete = ss.waitUntilBuilt(0);
        // Get the quarks before the full states to ensure that the attributes will be present in the full state
        List<Integer> quarks = fXmlEntry.getQuarks();
        fLock.writeLock().lock();
        try {
            List<ITmfStateInterval> fullState = ss.queryFullState(ss.getCurrentEndTime());
            ImmutableList.Builder<ITmfTreeDataModel> builder = ImmutableList.builder();
            builder.add(new TmfTreeDataModel(fTraceId, -1, Collections.singletonList(getTrace().getName())));

            for (int quark : quarks) {
                String seriesName = ss.getAttributeName(quark);
                if (seriesNameAttrib != null) {
                    // Use the value of the series name attribute
                    int seriesNameQuark = seriesNameAttrib.getQuark(quark, fXmlEntry);
                    Object value = fullState.get(seriesNameQuark).getValue();
                    if (value != null) {
                        seriesName = String.valueOf(value);
                    }
                }
                if (!seriesName.isEmpty()) {
                    String tempSeriesName = seriesName;
                    String uniqueName = fQuarkToString.computeIfAbsent(quark, q -> getUniqueNameFor(tempSeriesName));
                    // Check if an ID has already been created for this quark.
                    Long id = fIdToQuark.inverse().computeIfAbsent(quark, q -> ENTRY_IDS.getAndIncrement());
                    builder.add(new TmfTreeDataModel(id, fTraceId, Collections.singletonList(uniqueName)));
                }
            }

            ImmutableList<ITmfTreeDataModel> list = builder.build();
            if (isComplete) {
                TmfModelResponse<TmfTreeModel<ITmfTreeDataModel>> tmfModelResponse = new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), list), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
                fCached = tmfModelResponse;
                return tmfModelResponse;
            }
            return new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), list), ITmfResponse.Status.RUNNING, CommonStatusMessage.RUNNING);
        } catch (StateSystemDisposedException e) {
            return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, CommonStatusMessage.STATE_SYSTEM_FAILED);
        } finally {
            fLock.writeLock().unlock();
        }
    }

    private String getUniqueNameFor(String seriesName) {
        Integer quark = fQuarkToString.inverse().get(seriesName);
        int index = 1;
        String newName = seriesName;
        while (quark != null) {
            newName = seriesName + '(' + index + ')';
            quark = fQuarkToString.inverse().get(newName);
            index++;
        }
        return newName;
    }

    /**
     * @since 2.4
     */
    @Override
    public String getId() {
        return ID;
    }

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

    @Deprecated
    @Override
    public TmfModelResponse<List<ITmfTreeDataModel>> fetchTree(TimeQueryFilter filter, @Nullable IProgressMonitor monitor) {
        Map<String, Object> parameters = FetchParametersUtils.timeQueryToMap(filter);
        TmfModelResponse<@NonNull TmfTreeModel<@NonNull ITmfTreeDataModel>> response = fetchTree(parameters, monitor);
        TmfTreeModel<@NonNull ITmfTreeDataModel> model = response.getModel();
        List<ITmfTreeDataModel> treeModel = null;
        if (model != null) {
            treeModel = model.getEntries();
        }
        return new TmfModelResponse<>(treeModel, response.getStatus(), response.getStatusMessage());
    }
}
