/********************************************************************************
 * Copyright (c) 2015-2018 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.api.atfxadapter.transaction;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;

import org.asam.ods.AoException;
import org.asam.ods.ApplicationAttribute;
import org.asam.ods.ApplicationElement;
import org.asam.ods.ApplicationRelation;
import org.asam.ods.ApplicationStructure;
import org.asam.ods.BaseAttribute;
import org.asam.ods.BaseElement;
import org.asam.ods.BaseStructure;
import org.asam.ods.DataType;
import org.asam.ods.RelationRange;
import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Unit;
import org.eclipse.mdm.api.base.query.DataAccessException;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.query.ComparisonOperator;
import org.eclipse.mdm.api.base.query.Query;
import org.eclipse.mdm.api.base.query.QueryService;
import org.eclipse.mdm.api.base.query.Result;
import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
import org.eclipse.mdm.api.dflt.model.CatalogComponent;
import org.eclipse.mdm.api.dflt.model.CatalogSensor;
import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
import org.eclipse.mdm.api.odsadapter.utils.ODSEnumerations;
import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;

/**
 * Used to create, update or delete {@link CatalogComponent},
 * {@link CatalogSensor} and {@link CatalogAttribute} entities. Modifications of
 * the listed types results in modifications of the application model.
 *
 * @see org.eclipse.mdm.api.odsadapter.transaction.CatalogManager
 */
final class CatalogManager {

	private final ATFXTransaction transaction;

	private ApplicationStructure applicationStructure;
	private BaseStructure baseStructure;

	/**
	 * Constructor.
	 *
	 * @param transaction
	 *            The {@link ATFXTransaction}.
	 */
	CatalogManager(ATFXTransaction transaction) {
		this.transaction = transaction;
	}

	/**
	 * Creates for each given {@link CatalogComponent} a corresponding
	 * application element including all required application relations.
	 *
	 * @param catalogComponents
	 *            The {@code CatalogComponent}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 */
	public void createCatalogComponents(Collection<CatalogComponent> catalogComponents) throws AoException {
		Map<ContextType, List<CatalogComponent>> catalogComponentsByContextType = catalogComponents.stream()
				.collect(Collectors.groupingBy(CatalogComponent::getContextType));

		for (Entry<ContextType, List<CatalogComponent>> entry : catalogComponentsByContextType.entrySet()) {
			String odsContextTypeName = ODSUtils.CONTEXTTYPES.get(entry.getKey());
			ApplicationElement contextRootApplicationElement = getApplicationStructure()
					.getElementByName(odsContextTypeName);
			BaseElement contextRootBaseElement = contextRootApplicationElement.getBaseElement();
			ApplicationElement contextTemplateComponentApplicationElement = getApplicationStructure()
					.getElementByName("Tpl" + odsContextTypeName + "Comp");
			BaseElement baseElement = getBaseStructure().getElementByType("Ao" + odsContextTypeName + "Part");

			for (CatalogComponent catalogComponent : entry.getValue()) {
				ApplicationElement applicationElement = createApplicationElement(catalogComponent.getName(),
						baseElement);

				// relation context root to context component
				ApplicationRelation applicationRelation = getApplicationStructure().createRelation();
				applicationRelation.setElem1(contextRootApplicationElement);
				applicationRelation.setElem2(applicationElement);
				applicationRelation.setRelationName(catalogComponent.getName());
				applicationRelation.setInverseRelationName(odsContextTypeName);
				applicationRelation
						.setBaseRelation(getBaseStructure().getRelation(contextRootBaseElement, baseElement));
				applicationRelation._release();

				// relation template component to context component
				applicationRelation = getApplicationStructure().createRelation();
				applicationRelation.setElem1(contextTemplateComponentApplicationElement);
				applicationRelation.setElem2(applicationElement);
				applicationRelation.setRelationName(catalogComponent.getName());
				applicationRelation.setInverseRelationName("Tpl" + odsContextTypeName + "Comp");
				applicationRelation.setRelationRange(new RelationRange((short) 0, (short) -1));
				applicationRelation.setInverseRelationRange(new RelationRange((short) 1, (short) 1));

				// release resources
				applicationElement._release();
				applicationRelation._release();
			}

			// release resources
			contextTemplateComponentApplicationElement._release();
			contextRootApplicationElement._release();
			contextRootBaseElement._release();
			baseElement._release();
		}
	}

	/**
	 * Creates for each given {@link CatalogSensor} a corresponding application
	 * element including all required application relations.
	 *
	 * @param catalogSensors
	 *            The {@code CatalogSensor}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 */
	public void createCatalogSensors(Collection<CatalogSensor> catalogSensors) throws AoException {
		Map<String, List<CatalogSensor>> catalogSensorsByCatalogComponent = catalogSensors.stream()
				.collect(Collectors.groupingBy(cs -> cs.getCatalogComponent().getName()));

		ApplicationElement channelApplicationElement = getApplicationStructure().getElementByName("MeaQuantity");
		BaseElement channelBaseElement = channelApplicationElement.getBaseElement();

		for (Entry<String, List<CatalogSensor>> entry : catalogSensorsByCatalogComponent.entrySet()) {
			ApplicationElement contextComponentApplicationElement = getApplicationStructure()
					.getElementByName(entry.getKey());
			BaseElement contextComponentBaseElement = contextComponentApplicationElement.getBaseElement();
			ApplicationElement contextTemplateSensorApplicationElement = getApplicationStructure()
					.getElementByName("TplSensor");
			BaseElement baseElement = getBaseStructure().getElementByType("AoTestEquipmentPart");

			for (CatalogSensor catalogSensor : entry.getValue()) {
				ApplicationElement applicationElement = createApplicationElement(catalogSensor.getName(), baseElement);

				// relation context component to context sensor
				ApplicationRelation applicationRelation = getApplicationStructure().createRelation();
				applicationRelation.setElem1(contextComponentApplicationElement);
				applicationRelation.setElem2(applicationElement);
				applicationRelation.setRelationName(catalogSensor.getName());
				applicationRelation.setInverseRelationName(entry.getKey());
				applicationRelation
						.setBaseRelation(getBaseStructure().getRelation(contextComponentBaseElement, baseElement));
				applicationRelation._release();

				// relation template sensor to context sensor
				applicationRelation = getApplicationStructure().createRelation();
				applicationRelation.setElem1(contextTemplateSensorApplicationElement);
				applicationRelation.setElem2(applicationElement);
				applicationRelation.setRelationName(catalogSensor.getName());
				applicationRelation.setInverseRelationName("TplSensor");
				applicationRelation.setRelationRange(new RelationRange((short) 0, (short) -1));
				applicationRelation.setInverseRelationRange(new RelationRange((short) 1, (short) 1));
				applicationRelation._release();

				// relation channel to context sensor
				applicationRelation = getApplicationStructure().createRelation();
				applicationRelation.setElem1(channelApplicationElement);
				applicationRelation.setElem2(applicationElement);
				applicationRelation.setRelationName(catalogSensor.getName());
				applicationRelation.setInverseRelationName("MeaQuantity");
				applicationRelation.setBaseRelation(getBaseStructure().getRelation(channelBaseElement, baseElement));

				// release resources
				applicationElement._release();
				applicationRelation._release();
			}

			// release resources
			contextComponentApplicationElement._release();
			contextTemplateSensorApplicationElement._release();
			contextComponentBaseElement._release();
			baseElement._release();
		}

		// release resources
		channelApplicationElement._release();
		channelBaseElement._release();
	}

	/**
	 * Creates for each given {@link CatalogAttribute} a corresponding
	 * application attribute.
	 *
	 * @param catalogAttributes
	 *            The {@code CatalogAttribute}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 */
	public void createCatalogAttributes(Collection<CatalogAttribute> catalogAttributes) throws AoException {
		Map<String, List<CatalogAttribute>> catalogAttributesByCatalogComponent = catalogAttributes.stream()
				.collect(Collectors.groupingBy(CatalogManager::getParentName));

		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByCatalogComponent.entrySet()) {
			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());

			for (CatalogAttribute catalogAttribute : entry.getValue()) {

				ApplicationAttribute applicationAttribute = applicationElement.createAttribute();
				DataType dataType = ODSUtils.VALUETYPES.get(catalogAttribute.getValueType());
				applicationAttribute.setDataType(dataType);
				applicationAttribute.setName(catalogAttribute.getName());
				if (dataType == DataType.DT_ENUM) {
					applicationAttribute.setEnumerationDefinition(getApplicationStructure().getEnumerationDefinition(
							ODSEnumerations.getEnumName(catalogAttribute.getEnumerationObject())));
				}
				Optional<Unit> unit = catalogAttribute.getUnit();
				if (unit.isPresent()) {
					applicationAttribute.setUnit(ODSConverter.toODSID(unit.get().getID()));
				}

				// release resources
				applicationAttribute._release();
			}

			// release resources
			applicationElement._release();
		}
	}

	/**
	 * Updates the application attribute for each given
	 * {@link CatalogAttribute}.
	 *
	 * @param catalogAttributes
	 *            The {@code CatalogAttribute}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 */
	public void updateCatalogAttributes(List<CatalogAttribute> catalogAttributes) throws AoException {
		Map<String, List<CatalogAttribute>> catalogAttributesByCatalogComponent = catalogAttributes.stream()
				.collect(Collectors.groupingBy(CatalogManager::getParentName));

		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByCatalogComponent.entrySet()) {
			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());

			for (CatalogAttribute catalogAttribute : entry.getValue()) {

				ApplicationAttribute applicationAttribute = applicationElement
						.getAttributeByName(catalogAttribute.getName());

				Optional<Unit> unit = catalogAttribute.getUnit();
				if (unit.isPresent()) {
					applicationAttribute.setUnit(ODSConverter.toODSID(unit.get().getID()));
				}

				// release resources
				applicationAttribute._release();
			}

			// release resources
			applicationElement._release();
		}
	}

	/**
	 * Deletes the corresponding application element for each given
	 * {@link CatalogComponent}. Deleting a {@code CatalogComponent} is only
	 * allowed if it is not used in templates and all of its children could be
	 * deleted. So at first it is tried to delete its {@link CatalogAttribute}s
	 * and {@link CatalogSensor}s. On success it is ensured none of the given
	 * {@code
	 * CatalogComponent}s is used in templates. Finally the corresponding
	 * application elements are deleted.
	 *
	 * @param catalogComponents
	 *            The {@code CatalogComponent}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 * @throws DataAccessException
	 *             Thrown in case of errors.
	 */
	public void deleteCatalogComponents(Collection<CatalogComponent> catalogComponents)
			throws AoException, DataAccessException {
		List<CatalogAttribute> attributes = new ArrayList<>();
		List<CatalogSensor> sensors = new ArrayList<>();
		for (CatalogComponent catalogComponent : catalogComponents) {
			attributes.addAll(catalogComponent.getCatalogAttributes());
			sensors.addAll(catalogComponent.getCatalogSensors());
		}
		transaction.delete(sensors);
		transaction.delete(attributes);

		if (areReferencedInTemplates(catalogComponents)) {
			throw new DataAccessException(
					"Unable to delete given catalog components since at least " + "one is used in templates.");
		}

		for (CatalogComponent catalogComponent : catalogComponents) {
			ApplicationElement applicationElement = getApplicationStructure()
					.getElementByName(catalogComponent.getName());
			for (ApplicationRelation applicationRelation : applicationElement.getAllRelations()) {
				getApplicationStructure().removeRelation(applicationRelation);

				// release resources
				applicationRelation._release();
			}
			getApplicationStructure().removeElement(applicationElement);

			// release resources
			applicationElement._release();
		}
	}

	/**
	 * Deletes the corresponding application element for each given
	 * {@link CatalogSensor}. Deleting a {@code CatalogSensor} is only allowed
	 * if it is not used in templates and all of its children could be deleted.
	 * So at first it is tried to delete its {@link CatalogAttribute}s. On
	 * success it is ensured none of the given {@code CatalogSensor}s is used in
	 * templates. Finally the corresponding application elements are deleted.
	 *
	 * @param catalogSensors
	 *            The {@code CatalogSensor}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 * @throws DataAccessException
	 *             Thrown in case of errors.
	 */
	public void deleteCatalogSensors(Collection<CatalogSensor> catalogSensors) throws AoException, DataAccessException {
		List<CatalogAttribute> attributes = new ArrayList<>();
		for (CatalogSensor catalogSensor : catalogSensors) {
			attributes.addAll(catalogSensor.getCatalogAttributes());
		}
		transaction.delete(attributes);

		if (areReferencedInTemplates(catalogSensors)) {
			throw new DataAccessException(
					"Unable to delete given catalog sensors since at " + "least one is used in templates.");
		}

		for (CatalogSensor catalogSensor : catalogSensors) {
			ApplicationElement applicationElement = getApplicationStructure().getElementByName(catalogSensor.getName());
			for (ApplicationRelation applicationRelation : applicationElement.getAllRelations()) {
				getApplicationStructure().removeRelation(applicationRelation);

				// release resources
				applicationRelation._release();
			}
			getApplicationStructure().removeElement(applicationElement);

			// release resources
			applicationElement._release();
		}

	}

	/**
	 * Deletes the corresponding application attributes for each given
	 * {@link CatalogAttribute}. Deleting a {@code CatalogAttribute} is only
	 * allowed if it is not used in templates. So at first it is ensured none of
	 * the given {@code CatalogAttribute}s is used in templates and finally the
	 * corresponding application attributes are deleted.
	 *
	 * @param catalogAttributes
	 *            The {@code CatalogAttribute}s.
	 * @throws AoException
	 *             Thrown in case of errors.
	 * @throws DataAccessException
	 *             Thrown in case of errors.
	 */
	public void deleteCatalogAttributes(Collection<CatalogAttribute> catalogAttributes)
			throws AoException, DataAccessException {
		if (areReferencedInTemplates(catalogAttributes)) {
			throw new DataAccessException(
					"Unable to delete given catalog attributes since at least " + "one is used in templates.");
		}

		Map<String, List<CatalogAttribute>> catalogAttributesByParent = catalogAttributes.stream()
				.collect(Collectors.groupingBy(CatalogManager::getParentName));

		for (Entry<String, List<CatalogAttribute>> entry : catalogAttributesByParent.entrySet()) {
			ApplicationElement applicationElement = getApplicationStructure().getElementByName(entry.getKey());

			for (CatalogAttribute catalogAttribute : entry.getValue()) {
				ApplicationAttribute applicationAttribute = applicationElement
						.getAttributeByName(catalogAttribute.getName());
				applicationElement.removeAttribute(applicationAttribute);

				// release resources
				applicationAttribute._release();
			}

			// release resources
			applicationElement._release();
		}
	}

	/**
	 * Releases cached resources.
	 */
	public void clear() {
		if (applicationStructure != null) {
			applicationStructure._release();
		}

		if (baseStructure != null) {
			baseStructure._release();
		}
	}

	/**
	 * Creates a new {@link ApplicationElement} with given name and
	 * {@link BaseElement}. The returned {@code ApplicationElement} will be
	 * created with the three mandatory {@link ApplicationAttribute}s for 'Id',
	 * 'Name' and 'MimeType'.
	 *
	 * @param name
	 *            The name of the application element.
	 * @param baseElement
	 *            The {@code BaseElement} the created {@code
	 * 		ApplicationElement} will be derived from.
	 * @return The created {@code ApplicationElement} is returned.
	 * @throws AoException
	 *             Thrown in case of errors.
	 */
	private ApplicationElement createApplicationElement(String name, BaseElement baseElement) throws AoException {
		ApplicationElement applicationElement = getApplicationStructure().createElement(baseElement);
		applicationElement.setName(name);

		// Id
		ApplicationAttribute idApplicationAttribute = applicationElement.getAttributeByBaseName("id");
		idApplicationAttribute.setName("Id");
		idApplicationAttribute.setDataType(DataType.DT_LONGLONG);
		idApplicationAttribute.setIsAutogenerated(true);

		// Name
		ApplicationAttribute nameApplicationAttribute = applicationElement.getAttributeByBaseName("name");
		nameApplicationAttribute.setName("Name");
		nameApplicationAttribute.setLength(50);

		// MimeType
		BaseAttribute mimeTypeBaseAttribute = baseElement.getAttributes("mime_type")[0];
		ApplicationAttribute mimeTypeApplicationAttribute = applicationElement.createAttribute();
		mimeTypeApplicationAttribute.setBaseAttribute(mimeTypeBaseAttribute);
		mimeTypeApplicationAttribute.setName("MimeType");
		mimeTypeApplicationAttribute.setDataType(DataType.DT_STRING);
		mimeTypeApplicationAttribute.setLength(256);
		mimeTypeApplicationAttribute.setIsObligatory(true);

		// release resources
		idApplicationAttribute._release();
		nameApplicationAttribute._release();
		mimeTypeApplicationAttribute._release();
		mimeTypeBaseAttribute._release();

		return applicationElement;
	}

	/**
	 * Returns the cached {@link ApplicationStructure}.
	 *
	 * @return The {@code ApplicationStructure} is returned.
	 * @throws AoException
	 *             Thrown if unable to access the {@code
	 * 		ApplicationStructure}.
	 */
	private ApplicationStructure getApplicationStructure() throws AoException {
		if (applicationStructure == null) {
			applicationStructure = transaction.getModelManager().getAoSession().getApplicationStructure();
		}

		return applicationStructure;
	}

	/**
	 * Returns the cached {@link BaseStructure}.
	 *
	 * @return The {@code BaseStructure} is returned.
	 * @throws AoException
	 *             Thrown if unable to access the {@code
	 * 		BaseStructure}.
	 */
	private BaseStructure getBaseStructure() throws AoException {
		if (baseStructure == null) {
			baseStructure = transaction.getModelManager().getAoSession().getBaseStructure();
		}

		return baseStructure;
	}

	/**
	 * Checks whether given {@link Entity}s are referenced in templates.
	 *
	 * @param entities
	 *            The checked entities ({@link CatalogComponent},
	 *            {@link CatalogSensor} or {@link CatalogAttribute}).
	 * @return Returns {@code true} if at least one entity is referenced in a
	 *         template.
	 * @throws AoException
	 *             Thrown on errors.
	 * @throws DataAccessException
	 *             Thrown on errors.
	 */
	private boolean areReferencedInTemplates(Collection<? extends Entity> entities)
			throws AoException, DataAccessException {
		Map<EntityType, List<Entity>> entitiesByEntityType = entities.stream()
				.collect(Collectors.groupingBy(transaction.getModelManager()::getEntityType));

		for (Entry<EntityType, List<Entity>> entry : entitiesByEntityType.entrySet()) {
			EntityType source = entry.getKey();
			EntityType target = transaction.getModelManager().getEntityType(source.getName().replace("Cat", "Tpl"));

			Query query = transaction.getContext().getQueryService()
					.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class))
					.createQuery().selectID(target).join(source, target);

			List<Result> results = query.fetch(Filter.and()
					.add(ComparisonOperator.IN_SET.create(source.getIDAttribute(), collectInstanceIDs(entry.getValue()))));
			if (results.size() > 0) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Collect the instance IDs of all given {@link Entity}s.
	 *
	 * @param entities
	 *            The {@link Entity}s.
	 * @return The instance IDs a {@code String[]} are turned.
	 */
	private static String[] collectInstanceIDs(List<Entity> entities) {
		String[] ids = new String[entities.size()];

		for (int i = 0; i < ids.length; i++) {
			ids[i] = entities.get(i).getID();
		}

		return ids;
	}

	/**
	 * Returns the parent name for given {@link CatalogAttribute}.
	 *
	 * @param catalogAttribute
	 *            The {@code CatalogAttribute}.
	 * @return The parent name is returned.
	 */
	private static String getParentName(CatalogAttribute catalogAttribute) {
		Optional<CatalogComponent> catalogComponent = catalogAttribute.getCatalogComponent();
		if (catalogComponent.isPresent()) {
			return catalogComponent.get().getName();
		}

		return catalogAttribute.getCatalogSensor()
				.orElseThrow(() -> new IllegalStateException("Parent entity is unknown.")).getName();
	}

}
