/*
 * Copyright (c) 2016 Gigatronik Ingolstadt GmbH and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.eclipse.mdm.api.odsadapter.transaction;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.asam.ods.AIDName;
import org.asam.ods.AIDNameValueSeqUnitId;
import org.asam.ods.AoException;
import org.asam.ods.T_LONGLONG;
import org.eclipse.mdm.api.base.model.Core;
import org.eclipse.mdm.api.base.model.Core.EntityStore;
import org.eclipse.mdm.api.base.model.Deletable;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.FileLink;
import org.eclipse.mdm.api.base.model.FilesAttachable;
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.query.Attribute;
import org.eclipse.mdm.api.base.query.DataAccessException;
import org.eclipse.mdm.api.base.query.EntityType;
import org.eclipse.mdm.api.base.query.Relation;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Insert statement is used to update entities and their children.
 *
 * @since 1.0.0
 * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
 */
final class UpdateStatement extends BaseStatement {

	// ======================================================================
	// Class variables
	// ======================================================================

	private static final Logger LOGGER = LoggerFactory.getLogger(UpdateStatement.class);

	// ======================================================================
	// Instance variables
	// ======================================================================

	private final Map<Class<? extends Entity>, List<Entity>> childrenToCreate = new HashMap<>();
	private final Map<Class<? extends Entity>, List<Entity>> childrenToUpdate = new HashMap<>();
	private final Map<Class<? extends Deletable>, List<Deletable>> childrenToRemove = new HashMap<>();
	private Map<String, List<Value>> updateMap = new HashMap<>();

	private final List<FileLink> fileLinkToUpload = new ArrayList<>();
	private final List<String> nonUpdatableRelationNames;
	private final boolean ignoreChildren;
	private final boolean isFilesAttachable;

	// ======================================================================
	// Constructors
	// ======================================================================

	/**
	 * Constructor.
	 *
	 * @param transaction
	 *            The owning {@link ODSTransaction}.
	 * @param entityType
	 *            The associated {@link EntityType}.
	 * @param ignoreChildren
	 *            If {@code true}, then child entities won't be processed.
	 */
	UpdateStatement(ODSTransaction transaction, EntityType entityType, boolean ignoreChildren) {
		super(transaction, entityType);

		nonUpdatableRelationNames = entityType.getInfoRelations().stream().map(Relation::getName)
				.collect(Collectors.toList());
		this.ignoreChildren = ignoreChildren;

		EntityConfig<?> entityConfig = getModelManager().getEntityConfig(getEntityType());
		isFilesAttachable = FilesAttachable.class.isAssignableFrom(entityConfig.getEntityClass());
	}

	// ======================================================================
	// Public methods
	// ======================================================================

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void execute(Collection<Entity> entities) throws AoException, DataAccessException, IOException {
		for (Entity entity : entities) {
			readEntityCore(extract(entity));
		}

		// TODO tracing progress in this method...

		List<AIDNameValueSeqUnitId> anvsuList = new ArrayList<>();
		T_LONGLONG aID = getEntityType().getODSID();

		if (!fileLinkToUpload.isEmpty()) {
			getTransaction().getUploadService().uploadParallel(fileLinkToUpload, null);
		}

		for (Entry<String, List<Value>> entry : updateMap.entrySet()) {
			if (nonUpdatableRelationNames.contains(entry.getKey())) {
				// skip "empty" informative relation sequence
				continue;
			}

			Attribute attribute = getEntityType().getAttribute(entry.getKey());

			AIDNameValueSeqUnitId anvsu = new AIDNameValueSeqUnitId();
			anvsu.attr = new AIDName(aID, entry.getKey());
			anvsu.unitId = ODSConverter.toODSLong(0);
			anvsu.values = ODSConverter.toODSValueSeq(attribute, entry.getValue());
			anvsuList.add(anvsu);
		}

		long start = System.currentTimeMillis();
		getApplElemAccess().updateInstances(anvsuList.toArray(new AIDNameValueSeqUnitId[anvsuList.size()]));
		long stop = System.currentTimeMillis();

		LOGGER.debug("{} " + getEntityType() + " instances updated in {} ms.", entities.size(), stop - start);

		// delete first to make sure naming collisions do not occur!
		for (List<Deletable> children : childrenToRemove.values()) {
			getTransaction().delete(children);
		}
		for (List<Entity> children : childrenToCreate.values()) {
			getTransaction().create(children);
		}
		for (List<Entity> children : childrenToUpdate.values()) {
			getTransaction().update(children);
		}
	}

	// ======================================================================
	// Private methods
	// ======================================================================

	/**
	 * Reads given {@link Core} and prepares its data to be written:
	 *
	 * <ul>
	 * <li>collect new and removed {@link FileLink}s</li>
	 * <li>collect property {@link Value}s</li>
	 * <li>collect foreign key {@code Value}s</li>
	 * <li>collect child entities for recursive create/update/delete</li>
	 * </ul>
	 *
	 * @param core
	 *            The {@code Core}.
	 * @throws DataAccessException
	 *             Thrown in case of errors.
	 */
	private void readEntityCore(Core core) throws DataAccessException {
		if (!core.getTypeName().equals(getEntityType().getName())) {
			throw new IllegalArgumentException("Entity core '" + core.getTypeName()
					+ "' is incompatible with current update statement for entity type '" + getEntityType() + "'.");
		}

		// add all entity values
		for (Value value : core.getAllValues().values()) {
			updateMap.computeIfAbsent(value.getName(), k -> new ArrayList<>()).add(value);
		}

		// collect file links
		fileLinkToUpload.addAll(core.getAddedFileLinks());
		List<FileLink> fileLinksToRemove = core.getRemovedFileLinks();
		if (isFilesAttachable && !fileLinksToRemove.isEmpty()) {
			getTransaction().getUploadService().addToRemove(fileLinksToRemove);
		}

		updateMap.computeIfAbsent(getEntityType().getIDAttribute().getName(), k -> new ArrayList<>())
				.add(getEntityType().getIDAttribute().createValue(core.getID()));

		// define "empty" values for ALL informative relations
		for (Relation relation : getEntityType().getInfoRelations()) {
			updateMap.computeIfAbsent(relation.getName(), k -> new ArrayList<>()).add(relation.createValue());
		}

		// preserve "empty" relation values for removed related entities
		EntityStore mutableStore = core.getMutableStore();
		mutableStore.getRemoved().stream().map(e -> getModelManager().getEntityType(e))
				.map(getEntityType()::getRelation).map(Relation::getName).forEach(nonUpdatableRelationNames::remove);

		// replace "empty" relation values with corresponding instance IDs
		setRelationIDs(mutableStore.getCurrent());

		collectChildEntities(core);

		getTransaction().addModified(core);
	}

	/**
	 * Collects child entities for recursive processing.
	 *
	 * @param core
	 *            The {@link Core}.
	 */
	private void collectChildEntities(Core core) {
		if (ignoreChildren) {
			return;
		}

		for (Entry<Class<? extends Deletable>, List<? extends Deletable>> entry : core.getChildrenStore().getCurrent()
				.entrySet()) {
			Map<Boolean, List<Entity>> patrition = entry.getValue().stream()
					.collect(Collectors.partitioningBy(e -> ODSUtils.isValidID(e.getID())));
			List<Entity> virtualEntities = patrition.get(Boolean.TRUE);
			if (virtualEntities != null && !virtualEntities.isEmpty()) {
				childrenToCreate.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(virtualEntities);
			}
			List<Entity> existingEntities = patrition.get(Boolean.FALSE);
			if (existingEntities != null && !existingEntities.isEmpty()) {
				childrenToUpdate.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(existingEntities);
			}
		}

		for (Entry<Class<? extends Deletable>, List<? extends Deletable>> entry : core.getChildrenStore().getRemoved()
				.entrySet()) {
			List<Deletable> toDelete = entry.getValue().stream().filter(e -> ODSUtils.isValidID(e.getID()))
					.collect(Collectors.toList());
			childrenToRemove.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()).addAll(toDelete);
		}
	}

	/**
	 * Overwrites empty foreign key {@link Value} containers.
	 *
	 * @param relatedEntities
	 *            The related {@link Entity}s.
	 */
	private void setRelationIDs(Collection<Entity> relatedEntities) {
		for (Entity relatedEntity : relatedEntities) {
			if (!ODSUtils.isValidID(relatedEntity.getID())) {
				throw new IllegalArgumentException("Related entity must be a persited entity.");
			}

			Relation relation = getEntityType().getRelation(getModelManager().getEntityType(relatedEntity));
			List<Value> relationValues = updateMap.get(relation.getName());
			if (relationValues == null) {
				throw new IllegalStateException("Relation '" + relation
						+ "' is incompatible with update statement for entity type '" + getEntityType() + "'");
			}
			relationValues.get(relationValues.size() - 1).set(relatedEntity.getID());
			nonUpdatableRelationNames.remove(relation.getName());
		}
	}

}
