/**
 ********************************************************************************
 * Copyright (c) 2015-2021 Robert Bosch GmbH and others.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Robert Bosch GmbH - initial API and implementation
 ********************************************************************************
 */

package org.eclipse.app4mc.amalthea.model.util;

import static org.eclipse.app4mc.amalthea.model.LabelAccessEnum.READ;
import static org.eclipse.app4mc.amalthea.model.LabelAccessEnum.WRITE;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
import org.eclipse.app4mc.amalthea.model.ClearEvent;
import org.eclipse.app4mc.amalthea.model.Condition;
import org.eclipse.app4mc.amalthea.model.ConditionConjunction;
import org.eclipse.app4mc.amalthea.model.ConditionDisjunction;
import org.eclipse.app4mc.amalthea.model.ConditionDisjunctionEntry;
import org.eclipse.app4mc.amalthea.model.EnumMode;
import org.eclipse.app4mc.amalthea.model.ExecutionNeed;
import org.eclipse.app4mc.amalthea.model.Group;
import org.eclipse.app4mc.amalthea.model.IActivityGraphItemContainer;
import org.eclipse.app4mc.amalthea.model.IExecutable;
import org.eclipse.app4mc.amalthea.model.Label;
import org.eclipse.app4mc.amalthea.model.LabelAccess;
import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;
import org.eclipse.app4mc.amalthea.model.LabelAccessStatistic;
import org.eclipse.app4mc.amalthea.model.MinAvgMaxStatistic;
import org.eclipse.app4mc.amalthea.model.ModeLabel;
import org.eclipse.app4mc.amalthea.model.ModeLabelCondition;
import org.eclipse.app4mc.amalthea.model.ModeLiteral;
import org.eclipse.app4mc.amalthea.model.ModeSwitch;
import org.eclipse.app4mc.amalthea.model.ModeSwitchEntry;
import org.eclipse.app4mc.amalthea.model.ModeValueCondition;
import org.eclipse.app4mc.amalthea.model.NumericMode;
import org.eclipse.app4mc.amalthea.model.NumericStatistic;
import org.eclipse.app4mc.amalthea.model.ProbabilitySwitch;
import org.eclipse.app4mc.amalthea.model.ProbabilitySwitchEntry;
import org.eclipse.app4mc.amalthea.model.Process;
import org.eclipse.app4mc.amalthea.model.RelationalOperator;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.RunnableCall;
import org.eclipse.app4mc.amalthea.model.ServerCall;
import org.eclipse.app4mc.amalthea.model.SetEvent;
import org.eclipse.app4mc.amalthea.model.SingleValueStatistic;
import org.eclipse.app4mc.amalthea.model.Switch;
import org.eclipse.app4mc.amalthea.model.SwitchEntry;
import org.eclipse.app4mc.amalthea.model.Ticks;
import org.eclipse.app4mc.amalthea.model.WaitEvent;
import org.eclipse.app4mc.amalthea.model.WhileLoop;
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.jdt.annotation.NonNull;

import com.google.common.primitives.Ints;

public class SoftwareUtil {

	// Suppress default constructor
	private SoftwareUtil() {
		throw new IllegalStateException("Utility class");
	}

	/**
	 * Traverse the contained call graph items and collect all items.
	 *
	 * @param container	call graph, group, ...
	 * @return
	 * 		List of ActivityGraphItems
	 */
	public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container) {
		return collectActivityGraphItems(container, null, ActivityGraphItem.class, null);
	}

	/**
	 * Traverse the contained call graph items and collect all items.
	 * Collection can be restricted to specific modes.
	 *
	 * @param container	call graph, group, ...
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of ActivityGraphItems
	 */
	public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(container, modes, ActivityGraphItem.class, null);
	}

	/**
	 * Traverse the contained call graph items and collect all items.
	 * Collection can be restricted to specific modes and filtered by a lambda expression.
	 *
	 * @param container	call graph, group, ...
	 * @param modes		(optional) - null works
	 * @param filter	lambda expression (e.g. "a -&gt; a instanceof LabelAccess")
	 * @return
	 * 		List of ActivityGraphItems
	 */
	public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes,
			final Function<ActivityGraphItem, Boolean> filter) {
		return collectActivityGraphItems(container, modes, ActivityGraphItem.class, filter);
	}

	/**
	 * Traverse the runnable items graph of a runnable and collect all items.
	 * Collection can be restricted to specific modes and filtered by class.
	 *
	 * @param container		call graph, group, ...
	 * @param modes			(optional) - null works
	 * @param targetClass	subclass of ActivityGraphItem that restricts the result
	 * @return
	 * 		List of T extends ActivityGraphItems
	 */
	public static <T extends ActivityGraphItem> EList<T> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass) {
		return collectActivityGraphItems(container, modes, targetClass, null);
	}

	/**
	 * Traverse the runnable items graph of a runnable and collect all items.
	 * Collection can be restricted to specific modes and filtered by class and lambda expression.
	 *
	 * @param container		call graph, group, ...
	 * @param modes			(optional) - null works
	 * @param targetClass	subclass of ActivityGraphItem that restricts the result
	 * @param filter		lambda expression (e.g. "a -&gt; a instanceof LabelAccess")
	 * @return
	 * 		List of T extends ActivityGraphItems
	 */
	public static <T extends ActivityGraphItem> EList<T> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass, final Function<T, Boolean> filter) {
		EList<T> itemList = new BasicEList<>();
		if (container != null) {
			collectActivityGraphItems(container.getItems(), modes, targetClass, filter, itemList);
		}
		return itemList;
	}


	private static <T extends ActivityGraphItem> void collectActivityGraphItems(final EList<ActivityGraphItem> input, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass, final Function<T, Boolean> filter, final List<T> itemList) {
		for (ActivityGraphItem item : input) {
			if (item instanceof Group) {
				// **** Group
				collectActivityGraphItems(((Group) item).getItems(), modes, targetClass, filter, itemList);
			} else if (item instanceof WhileLoop) {
				// **** WhileLoop
				collectWhileLoopItems((WhileLoop) item, modes, targetClass, filter, itemList);
			} else if (item instanceof Switch) {
				// **** Switch -> check conditions
				collectSwitchItems((Switch) item, modes, targetClass, filter, itemList);
			} else if (item instanceof ModeSwitch) {
				// **** ModeSwitch -> check conditions
				collectModeSwitchItems((ModeSwitch) item, modes, targetClass, filter, itemList);
			} else if (item instanceof ProbabilitySwitch) {
				// **** ProbabilitySwitch
				for (ProbabilitySwitchEntry pse : ((ProbabilitySwitch) item).getEntries()) {
					collectActivityGraphItems(pse.getItems(), modes, targetClass, filter, itemList);
				}
			} else if (targetClass.isInstance(item)) {
				T castedItem = targetClass.cast(item);
				if (filter == null || filter.apply(castedItem)) {
					itemList.add(castedItem);
				}
			}
		}
	}

	private static <T extends ActivityGraphItem> void collectWhileLoopItems(final WhileLoop loop, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass, final Function<T, Boolean> filter, final List<T> itemList) {
		collectActivityGraphItems(loop.getItems(), modes, targetClass, filter, itemList);
	}

	private static  <T extends ActivityGraphItem> void collectSwitchItems(final Switch genericSwitch, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass, final Function<T, Boolean> filter, final List<T> itemList) {
		boolean includeDefault = true;
		for (SwitchEntry se : genericSwitch.getEntries()) {
			if (modes == null) {
				collectActivityGraphItems(se.getItems(), modes, targetClass, filter, itemList);
			} else if (conditionIsSatisfiedBy(se.getCondition(), modes)) {
				collectActivityGraphItems(se.getItems(), modes, targetClass, filter, itemList);
				includeDefault = false;
				break;
			}
		}
		if (includeDefault && genericSwitch.getDefaultEntry() != null) {
			collectActivityGraphItems(genericSwitch.getDefaultEntry().getItems(), modes, targetClass, filter, itemList);
		}
	}

	private static <T extends ActivityGraphItem> void collectModeSwitchItems(final ModeSwitch modeSwitch, final EMap<ModeLabel, String> modes,
			final Class<T> targetClass, final Function<T, Boolean> filter, final List<T> itemList) {
		boolean includeDefault = true;
		for (ModeSwitchEntry mse : modeSwitch.getEntries()) {
			if (modes == null) {
				collectActivityGraphItems(mse.getItems(), modes, targetClass, filter, itemList);
			} else if (mse.getCondition().isSatisfiedBy(modes)) {
				collectActivityGraphItems(mse.getItems(), modes, targetClass, filter, itemList);
				includeDefault = false;
				break;
			}
		}
		if (includeDefault && modeSwitch.getDefaultEntry() != null) {
			collectActivityGraphItems(modeSwitch.getDefaultEntry().getItems(), modes, targetClass, filter, itemList);
		}
	}

	public static boolean conditionIsSatisfiedBy(Object condition, EMap<ModeLabel, String> context) {
		// no context defined => satisfied (no restriction)
		if (context == null) return true;

		// OR condition
		if (condition instanceof ConditionDisjunction) {
			return conditionIsSatisfiedBy((ConditionDisjunction) condition, context);
		}

		// AND condition
		if (condition instanceof ConditionConjunction) {
			return conditionIsSatisfiedBy((ConditionConjunction) condition, context);
		}

		// Compare the value of a mode label with a given value
		if (condition instanceof ModeValueCondition) {
			return conditionIsSatisfiedBy((ModeValueCondition) condition, context);
		}

		// Compare the values of two mode labels
		if (condition instanceof ModeLabelCondition) {
			return conditionIsSatisfiedBy((ModeLabelCondition) condition, context);
		}

		// no restriction for other types
		return true;
	}

	public static boolean conditionIsSatisfiedBy(ConditionDisjunction condition, EMap<ModeLabel, String> context) {
		// no context defined => satisfied (no restriction)
		if (context == null) return true;

		// OR condition
		for (ConditionDisjunctionEntry entry : condition.getEntries()) {
			if (conditionIsSatisfiedBy(entry, context)) {
				return true;
			}
		}
		return false;
	}

	public static boolean conditionIsSatisfiedBy(ConditionConjunction condition, EMap<ModeLabel, String> context) {
		// no context defined => satisfied (no restriction)
		if (context == null) return true;

		// AND condition
		for (Condition entry : condition.getEntries()) {
			if (!conditionIsSatisfiedBy(entry, context)) {
				return false;
			}
		}
		return true;
	}

	public static boolean conditionIsSatisfiedBy(ModeValueCondition condition, EMap<ModeLabel, String> context) {
		// no context defined => satisfied (no restriction)
		if (context == null) return true;

		// Compare the value of a mode label with a given value

		// check completeness of specified condition
		ModeLabel label = condition.getLabel();
		RelationalOperator relation = condition.getRelation();
		if (label == null || relation == RelationalOperator._UNDEFINED_) {
			return false;
		}

		// no value specified in context => satisfied (no restriction)
		String labelValue = context.get(label);
		return (labelValue == null)
				|| isTrue(label, label, relation, labelValue, condition.getValue());
	}

	public static boolean conditionIsSatisfiedBy(ModeLabelCondition condition, EMap<ModeLabel, String> context) {
		// no context defined => satisfied (no restriction)
		if (context == null) return true;

		// Compare the values of two mode labels

		// check completeness of specified condition
		ModeLabel label1 = condition.getLabel1();
		ModeLabel label2 = condition.getLabel2();
		RelationalOperator relation = condition.getRelation();
		if (label1 == null || label2 == null || relation == RelationalOperator._UNDEFINED_) {
			return false;
		}

		// no value specified in context => satisfied (no restriction)
		String labelValue1 = context.get(label1);
		String labelValue2 = context.get(label2);
		return labelValue1 == null || labelValue2 == null
				|| isTrue(label1, label2, relation, labelValue1, labelValue2);
	}

	private static boolean isTrue(ModeLabel label1, ModeLabel label2, RelationalOperator relation,
			String labelValue1, String labelValue2) {

		// check availability of modes and compatibility of mode label types
		if (label1 == null || label1.getMode() == null
				|| label2 == null || label2.getMode() == null
				|| label1.getMode() != label2.getMode()) {
			return false;
		}

		if (label1.getMode() instanceof EnumMode) {
			ModeLiteral literal1 = ((EnumMode) label1.getMode()).getLiteral(labelValue1);
			ModeLiteral literal2 = ((EnumMode) label2.getMode()).getLiteral(labelValue2);

			if (literal1 == null || literal2 == null) {
				return false;
			}

			switch (relation) {
			case EQUAL:
				return literal1 == literal2;
			case NOT_EQUAL:
				return literal1 != literal2;
			default:
				break;
			}
		}

		if (label1.getMode() instanceof NumericMode) {
			Integer int1 = Ints.tryParse(labelValue1);
			Integer int2 = Ints.tryParse(labelValue2);

			if (int1 == null || int2 == null) {
				return false;
			}

			switch (relation) {
			case EQUAL:
				return int1.equals(int2);
			case NOT_EQUAL:
				return ! int1.equals(int2);
			case GREATER_THAN:
				return int1 > int2;
			case LESS_THAN:
				return int1 < int2;
			default:
				break;
			}
		}

		return false;
	}

	/**
	 * Returns a set of labels accessed from the runnable
	 * @param runnable runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getAccessedLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class)
			.stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet());
	}

	/**
	 * Returns a set of labels read by the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getReadLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == READ))
				.stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet());
	}

	/**
	 * Returns a set of labels written by the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getWriteLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == WRITE))
			.stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet());
	}

	/**
	 * Returns a list of all label accesses of the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of LabelAccesses
	 */
	public static List<LabelAccess> getLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class);
	}

	/**
	 * Returns a list of read label accesses of the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of LabelAccesses
	 */
	public static List<LabelAccess> getReadLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == READ));
	}

	/**
	 * Returns a list of write label accesses of the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of LabelAccesses
	 */
	public static List<LabelAccess> getWriteLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == WRITE));
	}

	/**
	 * Returns a map: labels accessed from runnable -&gt; the corresponding label accesses
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccesses
	 */
	public static Map<Label, List<LabelAccess>> getLabelToLabelAccessMap(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getData() != null))
			.stream().collect(Collectors.groupingBy(LabelAccess::getData));
	}

	/**
	 * Returns a map: labels accessed by the runnable -&gt; the corresponding LabelAccessStatistics
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return Map:
	 * 		Label -&gt; List of LabelAccessStatistics
	 */
	public static Map<Label, List<LabelAccessStatistic>> getLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class,
					(la -> la.getData() != null && la.getStatistic() != null))
				.stream().collect(Collectors.groupingBy(
						LabelAccess::getData,
						Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) ));
	}

	/**
	 * Returns a map: labels read by the runnable -&gt; the corresponding LabelAccessStatistics
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccessStatistics
	 */
	public static Map<Label, List<LabelAccessStatistic>> getReadLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class,
				(la -> la.getData() != null && la.getStatistic() != null && la.getAccess() == READ))
			.stream().collect(Collectors.groupingBy(
					LabelAccess::getData,
					Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) ));
	}

	/**
	 * Returns a map: labels written by the runnable -&gt; the corresponding LabelAccessStatistics
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccessStatistics
	 */
	public static Map<Label, List<LabelAccessStatistic>> getWriteLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class,
				(la -> la.getData() != null && la.getStatistic() != null && la.getAccess() == WRITE))
			.stream().collect(Collectors.groupingBy(
					LabelAccess::getData,
					Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) ));
	}

	/**
	 * Returns a set of labels accessed by the process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getAccessedLabelSet(Process process, EMap<ModeLabel, String> modes) {
		HashSet<Label> result = new HashSet<>();
		for (Runnable r : getRunnableList(process, modes))
			result.addAll(getAccessedLabelSet(r, modes));
		return result;
	}

	/**
	 * Returns a set of labels read by the process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getReadLabelSet(Process  process, EMap<ModeLabel, String> modes) {
		HashSet<Label> result = new HashSet<>();
		for (Runnable r : getRunnableList(process, modes))
			result.addAll(getReadLabelSet(r, modes));
		return result;
	}

	/**
	 * Returns a set of labels written by the process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Label> getWriteLabelSet(Process process, EMap<ModeLabel, String> modes) {
		HashSet<Label> result = new HashSet<>();
		for (Runnable r : getRunnableList(process, modes))
			result.addAll(getWriteLabelSet(r, modes));
		return result;
	}

	/**
	 * Returns a list of all label accesses of the process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of LabelAccesses
	 */
	public static List<LabelAccess> getLabelAccessList(Process process, EMap<ModeLabel, String> modes) {
		ArrayList<LabelAccess> result = new ArrayList<>();
		for (Runnable r : getRunnableList(process, modes))
			result.addAll(getLabelAccessList(r, modes));
		return result;
	}

	/**
	 * Returns a map: accessed labels of the process -&gt; the corresponding label accesses
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccess
	 */
	public static Map<Label, List<LabelAccess>> getLabelToLabelAccessMap(Process process, EMap<ModeLabel, String> modes) {
		HashMap<Label, List<LabelAccess>> result = new HashMap<>();
		for (Runnable run : getRunnableList(process, modes)) {
			Map<Label, List<LabelAccess>> labelToLabelAccessMap = SoftwareUtil.getLabelToLabelAccessMap(run, modes);
			for(Entry<Label, List<LabelAccess>> entry : labelToLabelAccessMap.entrySet()) {
				Label label = entry.getKey();
				List<LabelAccess> accesses = entry.getValue();

				List<LabelAccess> accessList = result.computeIfAbsent(label, k -> new ArrayList<>());
				accessList.addAll(accesses);
			}
		}
		return result;
	}

	/**
	 * Returns a map: labels accessed by the process -&gt; the corresponding label access statistics
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccessStatistic
	 */
	public static Map<Label, List<LabelAccessStatistic>> getLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) {
		HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>();
		for (Runnable r : getRunnableList(process, modes)) {
			Map<Label, List<LabelAccessStatistic>> labelToLabelAccessMap = SoftwareUtil.getLabelAccessStatisticsMap(r, modes);
			for(Entry<Label, List<LabelAccessStatistic>> entry : labelToLabelAccessMap.entrySet()) {
				Label label = entry.getKey();
				List<LabelAccessStatistic> statistics = entry.getValue();

				List<LabelAccessStatistic> statisticsList = result.computeIfAbsent(label, k -> new ArrayList<>());
				statisticsList.addAll(statistics);
			}
		}
		return result;
	}

	/**
	 * Returns a map: labels read the process -&gt; the corresponding label access statistics
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccessStatistic
	 */
	public static Map<Label, List<LabelAccessStatistic>> getReadLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) {
		HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>();
		for (Runnable run : getRunnableList(process, modes)) {
			Map<Label, List<LabelAccessStatistic>> readLabelAccessStatisticsMap = SoftwareUtil.getReadLabelAccessStatisticsMap(run, modes);
			for(Entry<Label, List<LabelAccessStatistic>> entry : readLabelAccessStatisticsMap.entrySet()) {
				Label label = entry.getKey();
				List<LabelAccessStatistic> statistics = entry.getValue();

				List<LabelAccessStatistic> statisticsList = result.computeIfAbsent(label, k -> new ArrayList<>());
				statisticsList.addAll(statistics);
			}
		}
		return result;
	}

	/**
	 * Returns a map: labels written by the process -&gt; the corresponding label access statistics
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Map: Label -&gt; List of LabelAccessStatistic
	 */
	public static Map<Label, List<LabelAccessStatistic>> getWriteLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) {
		HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>();
		for (Runnable run : getRunnableList(process, modes)) {
			Map<Label, List<LabelAccessStatistic>> writeLabelAcessStatisticsMap = SoftwareUtil.getWriteLabelAccessStatisticsMap(run, modes);
			for(Entry<Label, List<LabelAccessStatistic>> entry : writeLabelAcessStatisticsMap.entrySet()) {
				Label label = entry.getKey();
				List<LabelAccessStatistic> statistics = entry.getValue();

				List<LabelAccessStatistic> statisticsList = result.computeIfAbsent(label, k -> new ArrayList<>());
				statisticsList.addAll(statistics);
			}
		}
		return result;
	}

	/**
	 * Returns the reads from a process to a certain label. Evaluates the LabelAccessStatistic.
	 * Definition of TimeType is possible. Null value returns the average case.
	 */
	public static float getLabelReadCount(Label label, Process process, EMap<ModeLabel, String> modes, TimeType timeType) {
		if (timeType == null)
			timeType = TimeType.ACET;

		EList<@NonNull LabelAccess> accessList = collectActivityGraphItems(
				process.getActivityGraph(),
				modes,
				LabelAccess.class,
				(la -> la.getAccess() == READ && la.getData() == label));

		return sumUpLabelAccesses(timeType, accessList);
	}

	/**
	 * Returns the writes from a process to a certain label. Evaluates the LabelAccessStatistic.
	 * Definition of TimeType is possible. Null value returns the average case.
	 */
	public static float getLabelWriteCount(Label label, Process process, EMap<ModeLabel, String> modes, TimeType timeType) {
		if (timeType == null)
			timeType = TimeType.ACET;

		EList<@NonNull LabelAccess> accessList = collectActivityGraphItems(
				process.getActivityGraph(),
				modes,
				LabelAccess.class,
				(la -> la.getAccess() == WRITE && la.getData() == label));

		return sumUpLabelAccesses(timeType, accessList);
	}

	private static float sumUpLabelAccesses(TimeType timeType, EList<@NonNull LabelAccess> accessList) {
		float accesses = 0f;
		for (LabelAccess la : accessList) {
			if (la.getStatistic() == null || la.getStatistic().getValue() == null) {
				accesses += 1f;
				continue;
			}

			NumericStatistic statistic = la.getStatistic().getValue();
			if (statistic instanceof SingleValueStatistic) {
				accesses += ((SingleValueStatistic) statistic).getValue();
			} else if (statistic instanceof MinAvgMaxStatistic) {
				MinAvgMaxStatistic stat = (MinAvgMaxStatistic) statistic;
				switch (timeType) {
				case ACET:
					accesses += stat.getAvg();
					break;
				case BCET:
					accesses += stat.getMin();
					break;
				case WCET:
					accesses += stat.getMax();
					break;
				}
			}
		}
		return accesses;
	}

	/**
	 * Returns a list of runnables called by the process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Runnables
	 */
	public static List<Runnable> getRunnableList(Process process, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(process.getActivityGraph(), modes, RunnableCall.class)
			.stream().map(RunnableCall::getRunnable).filter(Objects::nonNull).collect(Collectors.toList());
	}

	/**
	 * Returns a set of runnables called by the process - no duplicates
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of runnables called by the process
	 */
	public static Set<Runnable> getRunnableSet(Process process, EMap<ModeLabel, String> modes) {
		return new HashSet<>(getRunnableList(process, modes));
	}

	/**
	 * Returns the number of label accesses from a statistic.
	 * The accType defines if the minimum, maximum or average accesses are returned.
	 */
	public static float getLabelAccessCountFromStatistics(LabelAccess labelAcc, TimeType accType) {
		if (labelAcc.getStatistic() == null)
			return 1;

		float accesses = 1;
		final NumericStatistic value = labelAcc.getStatistic().getValue();
		if (value instanceof SingleValueStatistic) {
			accesses = ((SingleValueStatistic)value).getValue();
		} else if (value instanceof MinAvgMaxStatistic) {
			switch(accType) {
			case ACET:
				accesses = ((MinAvgMaxStatistic)value).getAvg();
				break;
			case BCET:
				accesses = ((MinAvgMaxStatistic)value).getMin();
				break;
			case WCET:
				accesses = ((MinAvgMaxStatistic)value).getMax();
				break;
			default:
				accesses = ((MinAvgMaxStatistic)value).getAvg();
			}
		}
		return accesses;
	}

	/**
	 * Returns a list of runnables reading the label
	 * @param label		label
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Runnables
	 */
	public static List<Runnable> getReaderListOfLabel(Label label, EMap<ModeLabel, String> modes) {
		ArrayList<Runnable> result = new ArrayList<>();
		for (LabelAccess la : label.getLabelAccesses()) {
			if (la.getAccess() == LabelAccessEnum.READ) {
				Runnable run = AmaltheaServices.getContainerOfType(la, Runnable.class);
				if (modes == null || modes.isEmpty() || (collectActivityGraphItems(run.getActivityGraph(), modes)).contains(la)) {
					result.add(AmaltheaServices.getContainerOfType(la, Runnable.class));
				}
			}
		}
		return result;
	}

	/**
	 * Returns a set of runnables reading the label
	 * @param label		label
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Labels
	 */
	public static Set<Runnable> getReadersSetOfLabel(Label label, EMap<ModeLabel, String> modes) {
		return new HashSet<>(getReaderListOfLabel(label, modes));
	}

	/**
	 * Returns a list of runnables writing the label
	 * @param label		label
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Runnables
	 */
	public static List<Runnable> getWriterListOfLabel(Label label, EMap<ModeLabel, String> modes) {
		ArrayList<Runnable> result = new ArrayList<>();
		for (LabelAccess la : label.getLabelAccesses()) {
			if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
				Runnable run = AmaltheaServices.getContainerOfType(la, Runnable.class);
				if (modes == null || modes.isEmpty() || (collectActivityGraphItems(run.getActivityGraph(), modes)).contains(la)) {
					result.add(AmaltheaServices.getContainerOfType(la, Runnable.class));
				}
			}
		}
		return result;
	}

	/**
	 * Returns a set of runnables writing the label
	 * @param label		label
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of Runnables
	 */
	public static Set<Runnable> getWriterSetOfLabel(Label label, EMap<ModeLabel, String> modes) {
		return new HashSet<>(getWriterListOfLabel(label, modes));
	}

	/**
	 * Collects a list of set events calls for a process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of SetEvents
	 */
	public static List<SetEvent> collectSetEvents(Process process, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(process.getActivityGraph(), modes, SetEvent.class);
	}

	/**
	 * Collects a list of clear event calls for a process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of ClearEvents
	 */
	public static List<ClearEvent> collectClearEvents(Process process, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(process.getActivityGraph(), modes, ClearEvent.class);
	}

	/**
	 * Collects a list of wait event calls for a process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of WaitEvents
	 */
	public static List<WaitEvent> collectWaitEvents(Process process, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(process.getActivityGraph(), modes, WaitEvent.class);
	}

	/**
	 * Collects a list of event calls (clear, set or wait) of a process
	 * @param process	process (Task or ISR)
	 * @param modes 	(optional) - null works
	 * @return
	 * 		List of CallSequenceItems
	 */
	public static List<ActivityGraphItem> collectEventsOfProcess(Process process, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(process.getActivityGraph(), modes,
				(call -> call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
	}

	/**
	 * Returns a list of all exchanged labels that are written by the sender process and read by the receiver process
	 * @param sender	process (Task or ISR)
	 * @param receiver	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Labels
	 */
	 public static List<Label> getInterTaskCommunication(Process sender, Process receiver, EMap<ModeLabel, String> modes) {
		ArrayList<Label> result = new ArrayList<>();
		result.addAll(getWriteLabelSet(sender, modes));
		result.retainAll(getReadLabelSet(receiver, modes));
		return result;
	}

	/**
	 * Returns a list of processes calling the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Processes
	 */
	public static List<Process> getCallingProcesses(Runnable runnable, EMap<ModeLabel, String> modes) {
		ArrayList<Process> result = new ArrayList<>();
		for (RunnableCall callerRC : runnable.getRunnableCalls()) {
			IExecutable caller = callerRC.getContainingExecutable(); // null if container is not of type IExecutable
			if (!(caller instanceof Process)) continue;

			Process proc = (Process) caller;
			if (modes != null && !modes.isEmpty()) {
				for (RunnableCall rc : collectActivityGraphItems(caller.getActivityGraph(), modes, RunnableCall.class)) {
					if (rc.getRunnable() == runnable) {
						result.add(proc);
						break;
					}
				}
			} else {
				result.add(proc);
			}
		}
		return result;
	}

	/**
	 * Returns a list of runnables directly calling the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Runnables
	 */
	public static List<Runnable> getCallingRunnables(Runnable runnable, EMap<ModeLabel, String> modes) {
		ArrayList<Runnable> result = new ArrayList<>();
		for (RunnableCall callerRC : runnable.getRunnableCalls()) {
			IExecutable caller = callerRC.getContainingExecutable();	// null if container is not of type IExecutable
			if (!(caller instanceof Runnable)) continue;

			Runnable run = (Runnable) caller;
			if (modes != null && !modes.isEmpty()) {
				for (RunnableCall rc : collectActivityGraphItems(caller.getActivityGraph(), modes, RunnableCall.class)) {
					if (rc.getRunnable() == runnable) {
						result.add(run);
						break;
					}
				}
			}
			else
				result.add(run);
		}
		return result;
	}

	/**
	 * Returns a list of runnables directly called by the runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Runnables
	 */
	public static List<Runnable> getCalledRunnables(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, RunnableCall.class)
			.stream().map(RunnableCall::getRunnable).filter(Objects::nonNull).collect(Collectors.toList());
	}

	/**
	 * Returns a list of all execution needs for a given runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of ExecutionNeeds
	 */
	public static List<ExecutionNeed> getExecutionNeeds(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, ExecutionNeed.class);

		// Should nested runnable calls also be included ? (potential cycles)
	}

	/**
	 * Returns a list of all execution needs for a given process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of ExecutionNeeds
	 */
	public static List<ExecutionNeed> getExecutionNeeds(Process process, EMap<ModeLabel, String> modes) {
		List<ExecutionNeed> result = new ArrayList<>();
		// add needs on process level
		result.addAll(collectActivityGraphItems(process.getActivityGraph(), modes, ExecutionNeed.class));
		// add needs of called runnables
		for (Runnable run : getRunnableList(process, modes)) {
			result.addAll(getExecutionNeeds(run, modes));
		}
		return result;
	}

	/**
	 * Returns a list of all ticks for a given runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Ticks
	 */
	public static List<Ticks> getTicks(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, Ticks.class);

		// Should nested runnable calls also be included ? (potential cycles)
	}

	/**
	 * Returns a list of all ticks for a given process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		List of Ticks
	 */
	public static List<Ticks> getTicks(Process process, EMap<ModeLabel, String> modes) {
		List<Ticks> result = new ArrayList<>();
		// add ticks on process level
		result.addAll(collectActivityGraphItems(process.getActivityGraph(), modes, Ticks.class));
		// add ticks of called runnables
		for(Runnable run : getRunnableList(process, modes)) {
			result.addAll(getTicks(run, modes));
		}
		return result;
	}

	/**
	 * Returns a set of server calls for a runnable
	 * @param runnable	runnable
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of ServerCall
	 */
	public static Set<ServerCall> getServerCallSet(Runnable runnable, EMap<ModeLabel, String> modes) {
		return collectActivityGraphItems(runnable.getActivityGraph(), modes, ServerCall.class).stream().collect(Collectors.toSet());
	}

	/**
	 * Returns a set of server calls for a process
	 * @param process	process (Task or ISR)
	 * @param modes		(optional) - null works
	 * @return
	 * 		Set of ServerCall
	 */
	public static Set<ServerCall> getServerCallSet(Process process, EMap<ModeLabel, String> modes) {
		HashSet<ServerCall> result = new HashSet<>();
		for (Runnable run : getRunnableList(process, modes)) {
			result.addAll(getServerCallSet(run, modes));
		}
		return result;
	}
}
