package ch.elexis.core.services;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import ch.elexis.core.model.ICodeElement;

/**
 * Interface for a service that can be used to load and store {@link ICodeElement} instances.
 * 
 * @author thomas
 *
 */
public interface ICodeElementService {
	
	public enum CodeElementTyp {
			SERVICE, DIAGNOSE, ARTICLE
	}
	
	public enum ContextKeys {
			CONSULTATION, COVERAGE, MANDATOR, LAW, DATE, TREE_ROOTS
	}
	
	/**
	 * Create a String representation of the {@link ICodeElement}. A {@link ICodeElement} can the be
	 * loaded using the {@link ICodeElementService#loadFromString(String, HashMap)} method.
	 * 
	 * @param element
	 * @return
	 */
	public default String storeToString(ICodeElement element){
		return element.getCodeSystemName() + "|" + element.getCode() + "|" + element.getText();
	}
	
	/**
	 * Load a {@link ICodeElement} instance using its String representation, generated using the
	 * {@link ICodeElementService#storeToString(ICodeElement)} method.<br/>
	 * <br/>
	 * The returned {@link ICodeElement} will have the same SystemName and Code property, the rest
	 * can differ from the {@link ICodeElement} used to generate the String. New imports of the
	 * {@link ICodeElement} dataset, or some value in the context can also change the returned
	 * object.
	 * 
	 * @param storeToString
	 * @param context may be <code>null</code>
	 * @return
	 */
	public default Optional<ICodeElement> loadFromString(String storeToString,
		Map<Object, Object> context){
		String[] parts = getStoreToStringParts(storeToString);
		// only system and code are relevant for loading 
		if (parts != null && parts.length > 1) {
			return loadFromString(parts[0], parts[1], context);
		}
		return Optional.empty();
	}
	
	/**
	 * Get the parts from the storeToString.<br/>
	 * <br/>
	 * <li>index 0, system</li>
	 * <li>index 1, code</li>
	 * <li>index 2, text</li>
	 * 
	 * @param storeToString
	 * @return
	 */
	public default String[] getStoreToStringParts(String storeToString){
		return storeToString.split("\\|");
	}
	
	/**
	 * Load a {@link ICodeElement} instance using its String representation, generated using the
	 * {@link ICodeElementService#storeToString(ICodeElement)} method.<br/>
	 * <br/>
	 * The returned {@link ICodeElement} will have the same SystemName and Code property, the rest
	 * can differ from the {@link ICodeElement} used to generate the String. New imports of the
	 * {@link ICodeElement} dataset, or some value in the context can also change the returned
	 * object.
	 * 
	 * @param storeToString
	 * @param context may be <code>null</code>
	 * @return
	 */
	public Optional<ICodeElement> loadFromString(String system, String code,
		Map<Object, Object> context);
	
	/**
	 * Get all available {@link ICodeElementServiceContribution}s available.
	 * 
	 * @param typ
	 * @return
	 */
	public List<ICodeElementServiceContribution> getContributionsByTyp(CodeElementTyp typ);
	
	/**
	 * Get the {@link ICodeElementServiceContribution} with matching {@link CodeElementTyp} and code
	 * system name.
	 * 
	 * @param typ
	 * @param codeSystemName
	 * @return
	 */
	public Optional<ICodeElementServiceContribution> getContribution(CodeElementTyp typ,
		String codeSystemName);
}

@@ -1038,32 +1038,127 @@
 Element)%7D method
+ (this is NOT equivalent to%0A%09 * the storeToString created by the %7B@link IStoreToStringService%7D)
 .%3Cbr/%3E%0A%09 * %3Cbr/%3E
@@ -2362,16 +2362,111 @@
 %7D method
+ (this is NOT equivalent to%0A%09 * the storeToString created by the %7B@link IStoreToStringService%7D)
 .%3Cbr/%3E%0A%09
@@ -2780,36 +2780,139 @@
 %09 * @param s
-toreToString
+ystem the code system name, e.g. %22Eigenartikel%22%0A%09 * @param code the code to load from, dependent on the code system
 %0A%09 * @param 

Update javadoc