/********************************************************************************
 * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 ********************************************************************************/

package org.eclipse.mdm.businessobjects.service;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.ejb.Stateless;

import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Environment;
import org.eclipse.mdm.api.dflt.ApplicationContext;
import org.eclipse.mdm.api.dflt.EntityManager;
import org.eclipse.mdm.api.dflt.model.EntityFactory;
import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
import org.eclipse.mdm.api.dflt.model.TemplateComponent;
import org.eclipse.mdm.api.dflt.model.TemplateRoot;
import org.eclipse.mdm.api.dflt.model.TemplateSensor;
import org.eclipse.mdm.api.dflt.model.TemplateTest;
import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage;
import org.eclipse.mdm.businessobjects.utils.EntityNotFoundException;
import org.eclipse.mdm.businessobjects.utils.EntityNotFoundException.Type;

import io.vavr.Tuple;
import io.vavr.Value;
import io.vavr.control.Try;

/**
 * {@link TemplateRoot} service handling corresponding operations
 * 
 * @author Philipp Schweinbenz, science+computing AG Tuebingen (Atos SE)
 * @author Alexander Nehmer, science+computing AG Tuebingen (Atos SE)
 *
 */
@Stateless
public class TemplateService extends EntityService {

	/**
	 * Create new version of {@link TemplateTest} with given name. The link linked
	 * {@link TemplateTestStep}s are copied.
	 * 
	 * @param sourceNameSupplier a {@link Value} with the source name (MDM
	 *                           {@link Environment} name)
	 * @param name               name of entity to create new version of
	 * @return new version of the {@link TemplateTestStep} with the given name
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> createTplTestVersion(String sourceName, String name) {
		return Try.of(() -> {
			List<TemplateTest> tplTests = getEntityManager(sourceName)
					.mapTry(em -> em.loadAll(TemplateTest.class, name)).get();
			if (tplTests.isEmpty()) {
				throw new EntityNotFoundException(TemplateTestStep.class, name, Type.NAME);
			}

			ApplicationContext appContext = connectorService.getContextByName(sourceName);
			EntityFactory entityFactory = appContext.getEntityFactory().get();
			EntityManager entityManager = appContext.getEntityManager().get();

			// get latest version
			Comparator<TemplateTest> versionComparator = Comparator.comparing(TemplateTest::getVersion);
			TemplateTest latestTplTest = tplTests.stream().max(versionComparator).get();

			TemplateTest newTplTest = entityFactory.createTemplateTest(latestTplTest.getName());
			newTplTest.setVersion(latestTplTest.getVersion() + 1);

			Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(entityManager,
					Tuple.of(newTplTest, DataAccessHelper.CREATE));

			// set TplTestSteps as in latestVersion
			for (TemplateTestStepUsage tplTestStepUsage : latestTplTest.getTemplateTestStepUsages()) {
				TemplateTestStepUsage newUsage = entityFactory.createTemplateTestStepUsage(tplTestStepUsage.getName(),
						newTplTest, tplTestStepUsage.getTemplateTestStep());
				DataAccessHelper.execute(entityManager, Tuple.of(newUsage, DataAccessHelper.CREATE));
			}

			return (T) entities.toArray()[0];
		});
	}

	/**
	 * Create new version of {@link TemplateTestStep} with given name. The linked
	 * TplRoots are copied from the given {@link TemplateTestStep}
	 * 
	 * @param sourceNameSupplier a {@link Value} with the source name (MDM
	 *                           {@link Environment} name)
	 * @param name               name of entity to create new version of
	 * @return new version of the {@link TemplateTestStep} with the given name
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> createTplTestStepVersion(String sourceName, String name) {
		return Try.of(() -> {
			List<TemplateTestStep> tplTestSteps = getEntityManager(sourceName)
					.mapTry(em -> em.loadAll(TemplateTestStep.class, name)).get();
			if (tplTestSteps.isEmpty()) {
				throw new EntityNotFoundException(TemplateTestStep.class, name, Type.NAME);
			}
			TemplateTestStep givenTplTestStep = tplTestSteps.get(0);
			ApplicationContext appContext = connectorService.getContextByName(sourceName);
			TemplateTestStep newTplTestStep = copyTplTestStep(appContext.getEntityFactory().get(),
					appContext.getEntityManager().get(), givenTplTestStep);
			Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(getEntityManager(sourceName).get(),
					Tuple.of(newTplTestStep, DataAccessHelper.CREATE));

			return (T) entities.toArray()[0];
		});
	}

	/**
	 * Create a copy of a given {@link TemplateTestStep} and set version to latest +
	 * 1
	 * 
	 * @param entityFactory    {@link EntityFactory} to create new
	 *                         {@link TemplateTestStep}
	 * @param entityManager    {@link EntityManager} to get last version of given
	 *                         {@link TemplateTestStep}
	 * @param givenTplTestStep {@link TemplateTestStep} to create new version of
	 * @return copy of the given {@link TemplateTestStep}
	 */
	private TemplateTestStep copyTplTestStep(EntityFactory entityFactory, EntityManager entityManager,
			TemplateTestStep givenTplTestStep) {

		TemplateTestStep newTemplateTestStep = entityFactory.createTemplateTestStep(givenTplTestStep.getName());
		Comparator<TemplateTestStep> versionComparator = Comparator.comparing(TemplateTestStep::getVersion);
		Optional<Integer> latestVersion = entityManager.loadAll(TemplateTestStep.class, newTemplateTestStep.getName())
				.stream().max(versionComparator).map(TemplateTestStep::getVersion);
		if (latestVersion.isPresent()) {
			newTemplateTestStep.setVersion(latestVersion.get() + 1);
		}

		for (TemplateRoot tplRoot : givenTplTestStep.getTemplateRoots()) {
			newTemplateTestStep.setTemplateRoot(tplRoot);
		}

		return newTemplateTestStep;
	}

	/**
	 * * Create new version of {@link TemplateRoot} with given id
	 * 
	 * @param sourceNameSupplier  a {@link Value} with the source name (MDM
	 *                            {@link Environment} name)
	 * @param contextTypeSupplier a {@link Value} with the contextType of entity to
	 *                            create new version of.
	 * @param id                  id of entity to create new version of
	 * @return new version of the {@link TemplateRoot} with the given id
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> createTplRootVersion(String sourceName, Value<ContextType> contextTypeSupplier,
			String id) {
		return Try.of(() -> {
			TemplateRoot givenTplRoot = find(sourceName, TemplateRoot.class, id, contextTypeSupplier).get();
			ApplicationContext appContext = connectorService.getContextByName(sourceName);
			TemplateRoot newTplRoot = copyTplRoot(appContext.getEntityFactory().get(),
					appContext.getEntityManager().get(), givenTplRoot);
			Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(getEntityManager(sourceName).get(),
					Tuple.of(newTplRoot, DataAccessHelper.CREATE));

			return (T) entities.toArray()[0];
		});
	}

	/**
	 * Create a copy of a given {@link TemplateRoot} and set version to latest + 1
	 * 
	 * @param entityFactory {@link EntityFactory} to create new {@link TemplateRoot}
	 * @param entityManager {@link EntityManager} to get last version of given
	 *                      {@link TemplateRoot}
	 * @param givenTplRoot  {@link TemplateRoot} to create new version of
	 * @return
	 */
	private TemplateRoot copyTplRoot(EntityFactory entityFactory, EntityManager entityManager,
			TemplateRoot givenTplRoot) {
		TemplateRoot newTemplateRoot = entityFactory.createTemplateRoot(givenTplRoot.getContextType(),
				givenTplRoot.getName());
		mergeEntities(givenTplRoot, newTemplateRoot, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE,
				TemplateRoot.ATTR_DATE_CREATED, TemplateRoot.ATTR_VERSION_STATE, TemplateRoot.ATTR_VERSION);
		// TODO pschweinbenzidf on 2019-03-21: Why is this not working correctly with
		// Versionable.COMPARATOR?
		Comparator<TemplateRoot> versionComparator = Comparator.comparing(TemplateRoot::getVersion);
		Optional<Integer> latestVersion = entityManager
				.loadAll(TemplateRoot.class, givenTplRoot.getContextType(), newTemplateRoot.getName()).stream()
				.max(versionComparator).map(TemplateRoot::getVersion);
		if (latestVersion.isPresent()) {
			newTemplateRoot.setVersion(latestVersion.get() + 1);
		}

		for (TemplateComponent tplComp : givenTplRoot.getTemplateComponents()) {
			TemplateComponent newTplComp = entityFactory.createTemplateComponent(tplComp.getName(), newTemplateRoot,
					tplComp.getCatalogComponent());
			mergeEntities(tplComp, newTplComp, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);

			copyTplAttrs(entityFactory, newTplComp, tplComp.getTemplateAttributes());
			copyChildComps(entityFactory, newTplComp, tplComp.getTemplateComponents());
			copyTplSensors(entityFactory, newTplComp, tplComp.getTemplateSensors());
		}

		return newTemplateRoot;
	}

	/**
	 * Copy given child {@link TemplateComponent}s into given
	 * {@link TemplateComponent}
	 * 
	 * @param entityFactory   {@link EntityFactory} to create new entities
	 * @param tplComp         {@link TemplateComponent} into given child
	 *                        {@link TemplateComponent}s shall be copied
	 * @param givenChildComps {@link TemplateComponent}s which shall be copied
	 */
	private void copyChildComps(EntityFactory entityFactory, TemplateComponent tplComp,
			List<TemplateComponent> givenChildComps) {
		for (TemplateComponent childComp : givenChildComps) {
			TemplateComponent newTplComp = tplComp.getTemplateComponents().stream()
					.filter(tc -> tc.getName().equals(childComp.getName())).findFirst().orElseGet(() -> entityFactory
							.createTemplateComponent(childComp.getName(), tplComp, childComp.getCatalogComponent()));
			mergeEntities(childComp, newTplComp, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);

			copyTplAttrs(entityFactory, newTplComp, childComp.getTemplateAttributes());
			copyChildComps(entityFactory, newTplComp, childComp.getTemplateComponents());
			copyTplSensors(entityFactory, newTplComp, childComp.getTemplateSensors());
		}
	}

	/**
	 * Copy given {@link TemplateAttribute}s into given {@link TemplateComponent}
	 * 
	 * @param entityFactory {@link EntityFactory} to create new entities
	 * @param tplComp       {@link TemplateComponent} into given
	 *                      {@link TemplateAttribute}s shall be copied
	 * @param givenTplAttrs {@link TemplateAttribute}s which shall be copied
	 */
	private void copyTplAttrs(EntityFactory entityFactory, TemplateComponent tplComp,
			List<TemplateAttribute> givenTplAttrs) {
		for (TemplateAttribute tplAttr : givenTplAttrs) {
			TemplateAttribute newTplAttr = tplComp.getTemplateAttributes().stream()
					.filter(ta -> ta.getName().equals(tplAttr.getName())).findFirst()
					.orElseGet(() -> entityFactory.createTemplateAttribute(tplAttr.getName(), tplComp));
			mergeEntities(tplAttr, newTplAttr, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
		}
	}

	/**
	 * Copy given {@link TemplateSeonsor}s into given {@link TemplateComponent}
	 * 
	 * @param entityFactory   {@link EntityFactory} to create new entities
	 * @param tplComp         {@link TemplateComponent} into given
	 *                        {@link TemplateSensor}s shall be copied
	 * @param givenTplSensors {@link TemplateSensor}s which shall be copied
	 */
	private void copyTplSensors(EntityFactory entityFactory, TemplateComponent tplComp,
			List<TemplateSensor> givenTplSensors) {
		for (TemplateSensor tplSensor : givenTplSensors) {
			TemplateSensor newTplSensor = tplComp.getTemplateSensors().stream()
					.filter(ts -> ts.getName().equals(tplSensor.getName())).findFirst()
					.orElseGet(() -> entityFactory.createTemplateSensor(tplSensor.getName(), tplComp,
							tplSensor.getCatalogSensor(), tplSensor.getQuantity()));
			mergeEntities(tplSensor, newTplSensor, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);

			for (TemplateAttribute tplSensorAttr : tplSensor.getTemplateAttributes()) {
				Optional<TemplateAttribute> newTplSensorAttr = newTplSensor.getTemplateAttributes().stream()
						.filter(ta -> ta.getName().equals(tplSensorAttr.getName())).findFirst();
				if (newTplSensorAttr.isPresent()) {
					mergeEntities(tplSensorAttr, newTplSensorAttr.get(), Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
				}
			}
		}
	}

	/**
	 * Merge given {@link Entity}s
	 *
	 * @param entity       original {@link Entity} which shall be merged into given
	 *                     updEntity
	 * @param updEntity    {@link Entity} which shall be updated by given entity
	 * @param ignoredAttrs optional attributes which are not merged
	 */
	private void mergeEntities(Entity entity, Entity updEntity, String... ignoredAttrs) {
		if (!entity.getClass().isAssignableFrom(updEntity.getClass())) {
			return;
		}
		Set<String> ingoredAttrs = new HashSet<>(Arrays.asList(ignoredAttrs));

		Map<String, org.eclipse.mdm.api.base.model.Value> entityValues = entity.getValues();
		Set<String> updEntityKeys = updEntity.getValues().keySet();

		for (Map.Entry<String, org.eclipse.mdm.api.base.model.Value> entry : entityValues.entrySet()) {
			String key = entry.getKey();
			if (!ingoredAttrs.contains(key) && updEntityKeys.contains(key)) {
				updEntity.getValue(entry.getKey()).set(entry.getValue().extract());
			}
		}
	}

}
