package org.eclipse.basyx.submodel.restapi;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;

/**
 * Provider that handles container properties. Container properties can contain other submodel elements.
 *
 * @author espen, conradi
 *
 */
public class MultiSubmodelElementProvider implements IModelProvider {
	// Constants for API-Access
	public static final String ELEMENTS = "submodelElements";
	public static final String VALUE = "value";

	// The VAB model provider containing the submodelElements this SubmodelElementProvider is based on
	// Assumed to be a map that maps idShorts to the submodel elements
	private IModelProvider modelProvider;

	/**
	 * Constructor based on a model provider that contains the container property
	 */
	public MultiSubmodelElementProvider(IModelProvider provider) {
		this.modelProvider = provider;
	}

	/**
	 * The elements are stored in a map => convert them to a list
	 */
	@SuppressWarnings("unchecked")
	protected Collection<Map<String, Object>> getElementsList() {
		Object elements = modelProvider.getModelPropertyValue("");
		Map<String, Map<String, Object>> all = (Map<String, Map<String, Object>>) elements;

		// Feed all ELements through their Providers, in case someting needs to be done to them (e.g. smElemCollections)
		return all.entrySet().stream().map(e -> (Map<String, Object>) getSingleElement(ELEMENTS + "/" + e.getKey())).collect(Collectors.toList());
	}

	/**
	 * Single elements can be directly accessed in maps => return a proxy
	 */
	private IModelProvider getElementProxy(String[] pathElements) {
		String idShort = pathElements[1];
		return new VABElementProxy(idShort, modelProvider);
	}

	private Object getSingleElement(String path) {
		// Build new proxy pointing at sub-property of a submodelelement and forward the
		// remaininig part of the path to an appropriate provider
		String[] pathElements = VABPathTools.splitPath(path);
		String qualifier = pathElements[0];
		IModelProvider elementProxy = getElementProxy(pathElements);

		if (qualifier.equals(ELEMENTS)) {
			String subPath = VABPathTools.buildPath(pathElements, 2);
			return new SubmodelElementProvider(elementProxy).getModelPropertyValue(subPath);
		} else {
			throw new MalformedRequestException("Given path '" + path + "' does not start with /submodelElements");
		}
	}

	@Override
	public Object getModelPropertyValue(String path) throws ProviderException {
		String[] pathElements = VABPathTools.splitPath(path);
		String qualifier = pathElements[0];
		
		if(!qualifier.equals(ELEMENTS)) {
			// No other qualifier in a submodel element container can be directly accessed
			throw new MalformedRequestException("Given path '" + path + "' does not start with /submodelElements");
		}
		
		if (pathElements.length == 1) {
			// returns all elements
			return getElementsList();
		} else {
			// The path requests a single Element
			return getSingleElement(path);
		}
	}

	@Override
	public void setModelPropertyValue(String path, Object newValue) throws ProviderException {
		String[] pathElements = VABPathTools.splitPath(path);
		String qualifier = pathElements[0];
		if (pathElements.length < 2 || !qualifier.equals(ELEMENTS)) {
			// only possible to set values in a data elements, currently
			throw new MalformedRequestException("Given path '" + path + "' is invalid for set");
		}

		IModelProvider elementProxy = getElementProxy(pathElements);
		String subPath = VABPathTools.buildPath(pathElements, 2);
		
		new SubmodelElementProvider(elementProxy).setModelPropertyValue(subPath, newValue);
	}

	@Override
	@SuppressWarnings("unchecked")
	public void createValue(String path, Object newEntity) throws ProviderException {
		String[] pathElements = VABPathTools.splitPath(path);
		String qualifier = pathElements[0];
		String subPath = VABPathTools.buildPath(pathElements, 2);
		

		if (!qualifier.equals(ELEMENTS)) {
			throw new MalformedRequestException("Given path '" + path + "' does not start with /submodelElements");
		}
		
		// Check if the passed element is a SubmodelElementCollection. If yes, the value
		// of the "value" key needs to be handled
		if (SubmodelElementCollection.isSubmodelElementCollection((Map<String, Object>) newEntity)) {
			SubmodelElementCollection smCollection = SubmodelElementCollection.createAsFacade((Map<String, Object>) newEntity);
			newEntity = SubmodelElementMapCollectionConverter.mapToSmECollection(smCollection);
		}

		if (pathElements.length == 2) {
			modelProvider.createValue(pathElements[1], newEntity);
		} else {
			IModelProvider elementProxy = getElementProxy(pathElements);
			new SubmodelElementProvider(elementProxy).createValue(subPath, newEntity);
		}
	}

	@Override
	public void deleteValue(String path) throws ProviderException {
		String[] pathElements = VABPathTools.splitPath(path);
		String qualifier = pathElements[0];
		String subPath;
		IModelProvider elementProvider;
		
		if (!qualifier.equals(ELEMENTS)) {
			throw new MalformedRequestException("Given path '" + path + "' does not start with /submodelElements");
		}

		// If the first Element is a Collection, use its Provider
		if(pathElements.length > 2) {
			IModelProvider elementProxy = getElementProxy(pathElements);
			elementProvider = new SubmodelElementProvider(elementProxy); 
			subPath = VABPathTools.buildPath(pathElements, 2);
		} else {
			elementProvider = modelProvider;
			subPath = VABPathTools.buildPath(pathElements, 1);
		}

		// Delete a specific submodel element
		elementProvider.deleteValue(subPath);
	}

	@Override
	public void deleteValue(String path, Object obj) {
		throw new MalformedRequestException("Delete with a passed argument not allowed");
	}

	@Override
	public Object invokeOperation(String path, Object... parameters) throws ProviderException {
		String[] pathElements = VABPathTools.splitPath(path);
		String subPath = VABPathTools.buildPath(pathElements, 2);

		String qualifier = pathElements[0];
		if (!qualifier.equals(ELEMENTS)) {
			throw new MalformedRequestException("Given path '" + path + "' does not start with /submodelElements");
		}
		
		IModelProvider elementProxy = getElementProxy(pathElements);
		return new SubmodelElementProvider(elementProxy).invokeOperation(subPath, parameters);
	}
}
