/**********************************************************************
 * 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.core.model.xy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
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.internal.tmf.core.model.TmfXyResponseFactory;
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
import org.eclipse.tracecompass.internal.tmf.core.model.tree.TmfTreeCompositeDataProvider;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderManager;
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
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.xy.ISeriesModel;
import org.eclipse.tracecompass.tmf.core.model.xy.ITmfCommonXAxisModel;
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.trace.ITmfTrace;

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

/**
 * Represents a base implementation of {@link ITmfTreeXYDataProvider} that
 * supports experiments. Clients of this data provider must provide a list of
 * {@link ITmfTreeXYDataProvider} for each trace in the experiment which
 * supports the provider. From the list of sub data provider, this data provider
 * will merge all responses into one.
 *
 * @param <M>
 *            The type of {@link ITmfTreeDataModel} that this composite's tree
 *            provider must return.
 * @param <P>
 *            The type of {@link ITmfTreeXYDataProvider} that this composite
 *            must encapsulate
 * @author Yonni Chen
 * @since 4.0
 */
public class TmfTreeXYCompositeDataProvider<M extends ITmfTreeDataModel, P extends ITmfTreeXYDataProvider<M>>
        extends TmfTreeCompositeDataProvider<M, P> implements ITmfTreeXYDataProvider<M> {
    private final String fTitle;

    /**
     * Constructor
     *
     * @param providers
     *            A factory that creates a list of data provider. Each data provider
     *            should be associated to a different trace.
     * @param title
     *            Chart's title
     * @param id
     *            the provider's ID
     */
    public TmfTreeXYCompositeDataProvider(List<P> providers, String title, String id) {
        super(providers, id);
        fTitle = title;
    }

    /**
     * Return a composite {@link ITmfTreeXYDataProvider} from a list of traces.
     *
     * @param traces
     *            A list of traces from which to generate a provider.
     * @param title
     *            Chart's title
     * @param id
     *            the provider's ID
     * @return null if the non of the traces returns a provider, the provider if the
     *         lists only return one, else a {@link TmfTreeXYCompositeDataProvider}
     *         encapsulating the providers
     */
    public static @Nullable ITmfTreeXYDataProvider<ITmfTreeDataModel> create(Collection<ITmfTrace> traces, String title, String id) {
        return create(traces, title, id, null);
    }

    /**
     * Return a composite {@link ITmfTreeXYDataProvider} from a list of traces.
     *
     * @param traces
     *            A list of traces from which to generate a provider.
     * @param title
     *            Chart's title
     * @param id
     *            the provider's ID
     * @param secondaryId
     *            The provider's secondaryId
     * @return null if the non of the traces returns a provider, the provider if the
     *         lists only return one, else a {@link TmfTreeXYCompositeDataProvider}
     *         encapsulating the providers
     */
    public static @Nullable ITmfTreeXYDataProvider<ITmfTreeDataModel> create(Collection<ITmfTrace> traces, String title, String id, @Nullable String secondaryId) {
        String providerId = secondaryId == null ? id : id + ':' + secondaryId;
        List<@NonNull ITmfTreeXYDataProvider<ITmfTreeDataModel>> providers = new ArrayList<>();
        for (ITmfTrace child : traces) {
            ITmfTreeXYDataProvider<ITmfTreeDataModel> provider = DataProviderManager.getInstance().getDataProvider(child, providerId, ITmfTreeXYDataProvider.class);
            if (provider != null) {
                providers.add(provider);
            }
        }
        if (providers.isEmpty()) {
            return null;
        } else if (providers.size() == 1) {
            return providers.get(0);
        }
        return new TmfTreeXYCompositeDataProvider<>(providers, title, providerId);
    }

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

    @Override
    public TmfModelResponse<ITmfXyModel> fetchXY(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
        /**
         * <pre>
         * Response status according to the provider's reponse statuses:
         *
         * * Cancelled -> The monitor is cancelled
         * * Failed -> At least one provider has failed
         * * Running -> At least one of the providers is running
         * * Completed -> All providers have completed
         * </pre>
         */
        List<P> providers = getProviders();
        // Get all the responses
        Collection<TmfModelResponse<ITmfXyModel>> responses = getXyResponses(fetchParameters, monitor, providers);

        if (monitor != null && monitor.isCanceled()) {
            return TmfXyResponseFactory.createCancelledResponse(CommonStatusMessage.TASK_CANCELLED);
        }
        // If one response is failed, return a failed response with a concatenation of the messages
        String failedMsg = handleFailedStatus(responses);
        if (failedMsg != null) {
            return TmfXyResponseFactory.createFailedResponse(failedMsg);
        }

        boolean allCommon = Iterables.all(providers, ITmfCommonXAxisModel.class::isInstance);
        // The query is considered complete if all providers are completed
        boolean isComplete = Iterables.all(responses, response -> response.getStatus() == ITmfResponse.Status.COMPLETED);
        if (allCommon) {
            ImmutableMap.Builder<String, IYModel> series = ImmutableMap.builder();
            responses.forEach(response -> {
                ITmfCommonXAxisModel model = (ITmfCommonXAxisModel) response.getModel();
                if (model != null) {
                    series.putAll(model.getYData());
                }
            });
            TimeQueryFilter filter = FetchParametersUtils.createTimeQuery(fetchParameters);
            if (filter == null) {
                return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.INCORRECT_QUERY_PARAMETERS);
            }
            return TmfXyResponseFactory.create(fTitle, filter.getTimesRequested(), series.build(), isComplete);
        }
        ImmutableMap.Builder<String, ISeriesModel> series = ImmutableMap.builder();
        responses.forEach(response -> {
            ITmfXyModel model = response.getModel();
            if (model != null) {
                series.putAll(model.getData());
            }
        });
        return TmfXyResponseFactory.create(fTitle, series.build(), isComplete);
    }

    private static @Nullable String handleFailedStatus(Collection<TmfModelResponse<ITmfXyModel>> responses) {
        if (Iterables.any(responses, response -> response.getStatus() == ITmfResponse.Status.FAILED)) {
            // All requests have failed, return a concatenation of their errors
            return responses.stream().map(TmfModelResponse::getStatusMessage)
                    .collect(Collectors.joining("\n")); //$NON-NLS-1$
        }
        // At least one is good, return null
        return null;
    }

    private Collection<TmfModelResponse<ITmfXyModel>> getXyResponses(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor, List<P> providers) {
        List<TmfModelResponse<ITmfXyModel>> responses = new ArrayList<>();
        for (P dataProvider : providers) {
            TmfModelResponse<ITmfXyModel> response = dataProvider.fetchXY(fetchParameters, monitor);
            responses.add(response);

            if (monitor != null && monitor.isCanceled()) {
                return responses;
            }
        }
        return responses;
    }

}
