package org.eclipse.basyx.aas.registration.restapi;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Map;

import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
import org.eclipse.basyx.aas.metamodel.map.descriptor.SubmodelDescriptor;
import org.eclipse.basyx.aas.registration.api.IAASRegistryService;
import org.eclipse.basyx.aas.registration.memory.InMemoryRegistry;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.exception.provider.ResourceAlreadyExistsException;
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;

/**
 * Connects an arbitrary IRegistryService implementation to the VAB
 * 
 * @author schnicke, conradi
 *
 */
public class DirectoryModelProvider implements IModelProvider {

	IAASRegistryService registry;

	public static final String PREFIX = "api/v1/registry";
	public static final String SUBMODELS = "submodels";

	public DirectoryModelProvider(IAASRegistryService registry) {
		this.registry = registry;
	}

	public DirectoryModelProvider() {
		this(new InMemoryRegistry());
	}

	/**
	 * Check for correctness of path and returns a stripped path (i.e. no leading
	 * prefix)
	 * 
	 * @param path
	 * @return
	 * @throws MalformedRequestException if path does not start with PERFIX "api/v1/registry"
	 */
	private String stripPrefix(String path) throws MalformedRequestException {
		path = VABPathTools.stripSlashes(path);
		if (!path.startsWith(PREFIX)) {
			throw new MalformedRequestException("Path " + path + " not recognized as registry path. Has to start with " + PREFIX);
		}
		path = path.replaceFirst(PREFIX, "");
		path = VABPathTools.stripSlashes(path);
		return path;
	}
	
	/**
	 * Splits a path and checks, that first element is not "submodels" and that the second one, if exists, is "submodels"
	 * 
	 * @param path the path to be splitted
	 * @return Array of path elements
	 * @throws MalformedRequestException if path is not valid
	 */
	private String[] splitPath(String path) throws MalformedRequestException {
		
		if(path.isEmpty()) {
			return new String[0];
		}
		
		String[] splitted = path.split("/");
		
		//Assumes "submodels" is not a valid AASId
		if(splitted[0].equals(SUBMODELS)) {
			throw new MalformedRequestException("Path must not start with " + SUBMODELS);
		}
		
		//If path contains more than one element, the second one has to be "submodels"
		if(splitted.length > 1 && !splitted[1].equals(SUBMODELS)) {
			throw new MalformedRequestException("Second path element must be (if present): " + SUBMODELS);
		}
		
		return splitted;
	}
	
	private String[] preparePath(String path) throws MalformedRequestException {
		path = stripPrefix(path);

		String[] splitted = splitPath(path);

		try {
			for (int i = 0; i < splitted.length; i++) {
				splitted[i] = URLDecoder.decode(splitted[i], "UTF-8");
			}
			return splitted;
		} catch (UnsupportedEncodingException e) {
			//Malformed request because of unsupported encoding
			throw new MalformedRequestException("Path has to be encoded as UTF-8 string.");
		}
	}
	
	/**
	 * Checks if a given Object is a Map and checks if it has the correct modelType
	 * 
	 * @param expectedModelType the modelType the Object is expected to have
	 * @param value the Object to be checked and casted
	 * @return the object casted to a Map
	 * @throws MalformedRequestException 
	 */
	@SuppressWarnings("unchecked")
	private Map<String, Object> checkModelType(String expectedModelType, Object value) throws MalformedRequestException {
		//check if the given value is a Map
		if(!(value instanceof Map)) {
			throw new MalformedRequestException("Given newValue is not a Map");
		}

		Map<String, Object> map = (Map<String, Object>) value;
		
		//check if the given Map contains an AAS
		String type = ModelType.createAsFacade(map).getName();
		
		//have to accept Objects without modeltype information,
		//as modeltype is not part of the public metamodel
		if(!expectedModelType.equals(type) && type != null) {
			throw new MalformedRequestException("Given newValue map has not the correct ModelType");
		}
		
		return map;
	}
	
	/**
	 * Makes sure, that given Object is an AASDescriptor by checking its ModelType<br />
	 * Creates a new AASDescriptor with the content of the given Map
	 * 
	 * @param value the AAS Map object
	 * @return an AAS
	 * @throws MalformedRequestException 
	 */
	private AASDescriptor createAASDescriptorFromMap(Object value) throws MalformedRequestException {
		Map<String, Object> map = checkModelType(AASDescriptor.MODELTYPE, value);
		AASDescriptor aasDescriptor = new AASDescriptor(map);
		return aasDescriptor;
	}
	
	/**
	 * Makes sure, that given Object is an SubmodelDescriptor by checking its ModelType<br />
	 * Creates a new SubmodelDescriptor with the content of the given Map
	 * 
	 * @param value the AAS Map object
	 * @return an AAS
	 * @throws MalformedRequestException 
	 */
	private SubmodelDescriptor createSMDescriptorFromMap(Object value) throws MalformedRequestException {
		Map<String, Object> map = checkModelType(SubmodelDescriptor.MODELTYPE, value);
		SubmodelDescriptor smDescriptor = new SubmodelDescriptor(map);
		return smDescriptor;
	}

	@Override
	public Object getModelPropertyValue(String path) throws ProviderException {
		String[] splitted = preparePath(path);

		//Path is empty, request for all AASDescriptors
		if (splitted.length == 0) {
			return registry.lookupAll();
		} else {
			
			//Given path consists only of an AAS Id
			if(splitted.length == 1) {
				AASDescriptor descriptor = registry.lookupAAS(new ModelUrn(splitted[0]));
				
				//Throw an Exception if the requested AAS does not exist 
				if(descriptor == null) {
					throw new ResourceNotFoundException("Specified AASid '" + splitted[0] + "' does not exist.");
				}
				return descriptor;
			
			//Given path consists of an AAS Id and "/submodels"
			//Request for all SubmodelDescriptors of given AAS
			} else if(splitted.length == 2) {
				return getSmDescriptorsFromAAS(new ModelUrn(splitted[0]));
			
			//Given path consists of an AAS Id and "/submodels/" and a SubmodelId
			//Request for the SubmodelDescriptor of given AAS with given id
			} else if(splitted.length == 3) {
				SubmodelDescriptor smDescriptor = getSmDescriptorFromAAS(new ModelUrn(splitted[0]), splitted[2]);
				if(smDescriptor == null) {
					throw new ResourceNotFoundException("Specified SubmodelId '" + splitted[2] + "' does not exist in AAS '" + splitted[0] + "'.");
				}
				return smDescriptor;
			}
			
			//path has more than three elements and is therefore invalid
			throw new MalformedRequestException("Given path '" + path + "' contains more than three path elements and is therefore invalid.");
		}
	}

	@Override
	public void setModelPropertyValue(String path, Object newValue) throws ProviderException {
		String[] splitted = preparePath(path);

		if (splitted.length > 0) { // Overwriting existing entry
			//if path contains more or less than an aasID after the prefix

			// Decode encoded path
			ModelUrn identifier = new ModelUrn(splitted[0]);
			
			if (splitted.length == 1) {
				// Typically, VAB SET should not create new entries. Nevertheless, the registry
				// API is defined to do it.
				registry.register(createAASDescriptorFromMap(newValue));
			} else if (splitted.length == 3) {
				SubmodelDescriptor smDesc = createSMDescriptorFromMap(newValue);
				registry.register(identifier, smDesc);
			} else {
				throw new MalformedRequestException("Unknown path " + path);
			}
		} else {
			throw new MalformedRequestException("Set with empty path is not supported by registry");
		}
	}

	@Override
	public void createValue(String path, Object newEntity) throws ProviderException {
		String[] splitted = preparePath(path);

		// Creating new entry
		if (splitted.length == 0) {
			
			AASDescriptor aas = createAASDescriptorFromMap(newEntity);
			
			// Check if resource does already exist
			try {
				registry.lookupAAS(aas.getIdentifier());
				throw new ResourceAlreadyExistsException("AAS with Id '" +
						aas.getIdentifier().getId() + "' already exists. Try update instead.");
			} catch (ResourceNotFoundException e) {
				registry.register(aas);
			}
			
		// Creating new submodel entry for existing aas
		} else if (splitted.length == 2) { 
			ModelUrn aasId = retrieveModelURN(splitted[0]);
			
			SubmodelDescriptor smDescriptor = createSMDescriptorFromMap(newEntity);
			
			//a submodel with this Id already exists in given aas
			//getSmDescriptorFromAAS also checks if aas exists
			try {
				getSmDescriptorFromAAS(aasId, smDescriptor.getIdShort());
				throw new ResourceAlreadyExistsException("A Submodel with id '" + smDescriptor.getIdShort() +
						"' already exists in aas '" + splitted[0] + "'. Try update instead.");
			} catch (ResourceNotFoundException e) {
				registry.register(aasId, smDescriptor);
			}
		} else {
			throw new MalformedRequestException("Create was called with an unsupported path: " + path);
		}
	}

	private ModelUrn retrieveModelURN(String str) {
		return new ModelUrn(str);
	}

	@Override
	public void deleteValue(String path) throws ProviderException {
		String[] splitted = preparePath(path);
			
		if (splitted.length == 1) { //delete an aas
			
			ModelUrn aasId = new ModelUrn(splitted[0]);
			
			//aas to be deleted does not exist
			if(registry.lookupAAS(aasId) == null) {
				throw new ResourceNotFoundException("AAS '" + splitted[0] + "' to be deleted does not exist.");
			}
			
			registry.delete(aasId);
			
		} else if(splitted.length == 3) { //delete a submodel
			ModelUrn aasId = new ModelUrn(splitted[0]);
			String smId = splitted[2];
			// a submodel with this Id does not exist in given aas
			// getSmDescriptorFromAAS also checks if aas exists
			if (getSmDescriptorFromAAS(aasId, smId) == null) {
				throw new ResourceNotFoundException("A Submodel with id '" + smId + "' does not exist in aas '" + splitted[0] + "'.");
			}

			registry.delete(aasId, smId);
		} else {
			throw new MalformedRequestException("Delete with empty path is not supported by registry");
		}
	}

	@Override
	public void deleteValue(String path, Object obj) throws ProviderException {
		throw new MalformedRequestException("DeleteValue with parameter not supported by registry");
	}

	@Override
	public Object invokeOperation(String path, Object... parameter) throws ProviderException {
		throw new MalformedRequestException("Invoke not supported by registry");
	}
	
	/**
	 * Gets all SubmodelDescriptor objects form an aas.
	 * Throws RuntimeException if aas does not exist.
	 * 
	 * @param id id of the aas
	 * @return Set of contained SubmodelDescriptor objects
	 * @throws ResourceNotFoundException if the AAS does not exist
	 */
	private Collection<SubmodelDescriptor> getSmDescriptorsFromAAS(IIdentifier id) throws ResourceNotFoundException {
		AASDescriptor aasDescriptor = registry.lookupAAS(id);
		if(aasDescriptor == null) {
			throw new ResourceNotFoundException("Specified AASid '" + id.getId() + "' does not exist.");
		}
		return aasDescriptor.getSubModelDescriptors();
	}
	
	/**
	 * Gets a specific SubmodelDescriptor form an aas.
	 * Throws RuntimeException if aas does not exist.
	 * 
	 * @param aasId id of the aas
	 * @param smId id of the submodel
	 * @return the SubmodelDescriptor with the given id
	 * @throws ResourceNotFoundException if aasId does not exist
	 */
	private SubmodelDescriptor getSmDescriptorFromAAS(IIdentifier aasId, String smId)
			throws ResourceNotFoundException {
		AASDescriptor aasDescriptor = registry.lookupAAS(aasId);
		if(aasDescriptor == null) {
			throw new ResourceNotFoundException("Specified AASId '" + aasId.getId() + "' does not exist.");
		}
		
		SubmodelDescriptor smDescriptor = aasDescriptor.getSubmodelDescriptorFromIdShort(smId);
		if (smDescriptor == null) {
			throw new ResourceNotFoundException("Specified SMId '" + smId + "' for AAS " + aasId.getId() + " does not exist.");
		}
		return smDescriptor;
	}

}
