package ch.elexis.core.model;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import ch.elexis.core.constants.Preferences;
import ch.elexis.core.jpa.entities.Bestellung;
import ch.elexis.core.jpa.model.adapter.AbstractIdDeleteModelAdapter;
import ch.elexis.core.model.service.holder.CoreModelServiceHolder;
import ch.elexis.core.model.util.internal.ModelUtil;

public class Order extends AbstractIdDeleteModelAdapter<ch.elexis.core.jpa.entities.Bestellung>
		implements IdentifiableWithXid, IOrder {
	
	public Order(Bestellung entity){
		super(entity);
	}
	
	@Override
	public List<IOrderEntry> getEntries(){
		CoreModelServiceHolder.get().refresh(this);
		return getEntity().getEntries().parallelStream().filter(b -> !b.isDeleted())
			.map(b -> ModelUtil.getAdapter(b, IOrderEntry.class, true))
			.collect(Collectors.toList());
	}
	
	@Override
	public IOrderEntry addEntry(IArticle article, IStock stock, IContact provider, int amount){
		if (provider == null) {
			String providerId =
				ModelUtil.getConfig(Preferences.INVENTORY_DEFAULT_ARTICLE_PROVIDER, null);
			if (providerId != null) {
				IContact defProvider = ModelUtil.load(providerId, IContact.class);
				provider = defProvider;
			}
		}
		
		IOrderEntry orderEntry = findOrderEntry(stock, article);
		if (orderEntry != null) {
			orderEntry.setAmount(orderEntry.getAmount() + amount);
			addChanged(orderEntry);
		} else {
			orderEntry = ModelUtil.getModelService().create(IOrderEntry.class);
			orderEntry.setArticle(article);
			orderEntry.setStock(stock);
			orderEntry.setProvider(provider);
			orderEntry.setAmount(amount);
			orderEntry.setOrder(this);
		}
		return orderEntry;
	}
	
	@Override
	public IOrderEntry findOrderEntry(IStock stock, IArticle article){
		List<IOrderEntry> entries = getEntries();
		for (IOrderEntry iOrderEntry : entries) {
			if (((iOrderEntry.getStock() == null && stock == null)
				|| (iOrderEntry.getStock() != null && iOrderEntry.getStock().equals(stock)))
				&& iOrderEntry.getArticle().equals(article)) {
				return iOrderEntry;
			}
		}
		return null;
	}
	
	@Override
	public LocalDateTime getTimestamp(){
		String id = getId();
		if (id != null) {
			String[] parts = id.split(":");
			if (parts.length >= 2) {
				return LocalDateTime.parse(parts[1], timestampFormatter);
			}
		}
		return null;
	}
	
	@Override
	public void setTimestamp(LocalDateTime value){
		updateId(value, getName());
	}
	
	@Override
	public String getName(){
		String id = getId();
		if (id != null && id.contains(":")) {
			String[] parts = id.split(":");
			if (parts.length >= 1) {
				return parts[0];
			}
		}
		return "";
	}
	
	@Override
	public void setName(String value){
		updateId(getTimestamp(), value);
	}
	
	private static DateTimeFormatter timestampFormatter =
		DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
	
	private void updateId(LocalDateTime timestamp, String name){
		if (timestamp == null) {
			throw new IllegalStateException("Can not update id without timestamp");
		}
		Optional<IContact> activeUser = ModelUtil.getActiveUserContact();
		String id = (name != null ? name : "") + ":"
			+ (timestamp != null ? timestamp.format(timestampFormatter) : "") + ":"
			+ (activeUser.isPresent() ? activeUser.get().getId() : "");
		getEntityMarkDirty().setId(id);
	}
	
	@Override
	public boolean isDone(){
		for (IOrderEntry iOrderEntry : getEntries()) {
			if (iOrderEntry.getState() != OrderEntryState.DONE) {
				return false;
			}
		}
		return true;
	}
}

@@ -95,24 +95,72 @@
 eFormatter;%0A
+import java.time.format.DateTimeParseException;%0A
 import java.
@@ -515,16 +515,46 @@
 delUtil;
+%0Aimport ch.rgw.tools.TimeTool;
 %0A%0Apublic
@@ -2405,24 +2405,35 @@
 gth %3E= 2) %7B%0A
+%09%09%09%09try %7B%0A%09
 %09%09%09%09return L
@@ -2482,16 +2482,183 @@
 atter);%0A
+%09%09%09%09%7D catch (DateTimeParseException e) %7B%0A%09%09%09%09%09// fallback using TimeTool parser%0A%09%09%09%09%09TimeTool tool = new TimeTool(parts%5B1%5D);%0A%09%09%09%09%09return tool.toLocalDateTime();%0A%09%09%09%09%7D%0A
 %09%09%09%7D%0A%09%09%7D

add TimeTool fallback to Order get timestamp