/********************************************************************************
 * 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.odsadapter.lookup;

import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.adapter.Relation;
import org.eclipse.mdm.api.base.model.ContextComponent;
import org.eclipse.mdm.api.base.model.ContextSensor;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Deletable;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.query.ComparisonOperator;
import org.eclipse.mdm.api.base.query.DataAccessException;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.query.Query;
import org.eclipse.mdm.api.base.query.QueryService;
import org.eclipse.mdm.api.base.query.Record;
import org.eclipse.mdm.api.base.query.Result;
import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
import org.eclipse.mdm.api.dflt.model.TemplateComponent;
import org.eclipse.mdm.api.dflt.model.TemplateSensor;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;

/**
 * Recursively loads entities for a given {@link EntityConfig} with all resolved
 * dependencies (optional, mandatory children).
 *
 * @param <T> The entity type.
 * @since 1.0.0
 * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
 */
public class EntityRequest<T extends Entity> {

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

	final ODSModelManager odsModelManager;
	final QueryService queryService;
	final EntityConfig<T> entityConfig;
	final EntityResult<T> entityResult = new EntityResult<>(this);

	final Cache cache;

	boolean filtered;

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

	/**
	 * Constructor.
	 *
	 * @param modelManager The {@link ODSModelManager}.
	 * @param config       The {@link EntityConfig}.
	 */
	public EntityRequest(ODSModelManager modelManager, QueryService queryService, Key<T> key) {
		this.odsModelManager = modelManager;
		this.queryService = queryService;
		this.entityConfig = modelManager.getEntityConfig(key);
		cache = new Cache();
	}

	/**
	 * Constructor.
	 *
	 * @param parentRequest The parent {@link EntityRequest}.
	 * @param entityConfig  The {@link EntityConfig}.
	 */
	protected EntityRequest(EntityRequest<?> parentRequest, EntityConfig<T> entityConfig) {
		odsModelManager = parentRequest.odsModelManager;
		queryService = parentRequest.queryService;
		cache = parentRequest.cache;
		this.entityConfig = entityConfig;
	}

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

	/**
	 * Loads all entities matching given name pattern.
	 *
	 * @param pattern Is always case sensitive and may contain wildcard characters
	 *                as follows: "?" for one matching character and "*" for a
	 *                sequence of matching characters.
	 * @return A sorted {@link List} with queried entities is returned.
	 * @throws DataAccessException Thrown if unable to load entities.
	 */
	public List<T> loadAll(String pattern) throws DataAccessException {
		return load(Filter.nameOnly(entityConfig.getEntityType(), pattern)).getSortedEntities();
	}

	/**
	 * Loads all entities matching given instance IDs.
	 *
	 * @param instanceIDs The instance IDs.
	 * @return A sorted {@link List} with queried entities is returned.
	 * @throws DataAccessException Thrown if unable to load entities.
	 */
	public List<T> loadAll(Collection<String> instanceIDs) throws DataAccessException {
		if (instanceIDs.isEmpty()) {
			// just to be sure...
			return Collections.emptyList();
		}

		return load(Filter.idsOnly(entityConfig.getEntityType(), instanceIDs)).getSortedEntities();
	}

	public ODSModelManager getODSModelManager() {
		return odsModelManager;
	}

	// ======================================================================
	// Protected methods
	// ======================================================================

	/**
	 * Adds foreign key select statements to given {@link Query} for each given
	 * {@link EntityConfig}.
	 *
	 * @param query          The {@link Query}.
	 * @param relatedConfigs The {@code EntityConfig}s.
	 * @param mandatory      Flag indicates whether given {@code EntityConfig}s are
	 *                       mandatory or not.
	 * @return For each {@code EntityConfig} a corresponding {@code
	 * 		RelationConfig} is returned in a {@code List}.
	 */
	protected List<RelationConfig> selectRelations(Query query, List<EntityConfig<?>> relatedConfigs,
			boolean mandatory) {
		List<RelationConfig> relationConfigs = new ArrayList<>();
		EntityType entityType = entityConfig.getEntityType();
		for (EntityConfig<?> relatedEntityConfig : relatedConfigs) {
			RelationConfig relationConfig = new RelationConfig(entityType, relatedEntityConfig, mandatory);
			query.select(relationConfig.relation.getAttribute());
			relationConfigs.add(relationConfig);
		}

		return relationConfigs;
	}

	/**
	 * Convenience method collects the queried {@link Record} from each
	 * {@link Result}.
	 *
	 * @param results The {@code Result}s.
	 * @return The queried {@link Record}s are returned.
	 */
	protected List<Record> collectRecords(List<Result> results) {
		return results.stream().map(r -> r.getRecord(entityConfig.getEntityType())).collect(toList());
	}

	/**
	 * Loads and maps related entities for each given {@link RelationConfig}.
	 *
	 * @param relationConfigs The {@code RelationConfig}s.
	 * @throws DataAccessException Thrown if unable to load related entities.
	 */
	protected void loadRelatedEntities(List<RelationConfig> relationConfigs) throws DataAccessException {
		for (RelationConfig relationConfig : relationConfigs) {
			EntityConfig<?> relatedConfig = relationConfig.entityConfig;

			boolean isContextTypeDefined = entityConfig.getContextType().isPresent();
			for (Entity relatedEntity : new EntityRequest<>(this, relatedConfig)
					.loadAll(relationConfig.dependants.keySet())) {
				boolean setByContextType = !isContextTypeDefined && relatedConfig.getContextType().isPresent();
				for (EntityRecord<?> entityRecord : relationConfig.dependants.remove(relatedEntity.getID())) {
					setRelatedEntity(entityRecord, relatedEntity,
							setByContextType ? relatedConfig.getContextType().get() : null);
				}
			}

			if (!relationConfig.dependants.isEmpty()) {
				// this may occur if the instance id of the related entity
				// is defined, but the entity itself does not exist
				throw new IllegalStateException(
						"Unable to load related entities: " + relationConfig.dependants.toString());
			}
		}
	}

	/**
	 * Assigns given related {@link Entity} to given {@link EntityRecord}.
	 *
	 * @param entityRecord  The {@code EntityRecord} which references given
	 *                      {@code Entity}.
	 * @param relatedEntity The related {@code Entity}.
	 * @param contextType   Used as qualifier for relation assignment.
	 */
	protected void setRelatedEntity(EntityRecord<?> entityRecord, Entity relatedEntity, ContextType contextType) {
		if (contextType == null) {
			entityRecord.core.getMutableStore().set(relatedEntity);
		} else {
			entityRecord.core.getMutableStore().set(relatedEntity, contextType);
		}

		List<TemplateAttribute> templateAttributes = new ArrayList<>();
		if (entityRecord.entity instanceof ContextComponent && relatedEntity instanceof TemplateComponent) {
			templateAttributes.addAll(((TemplateComponent) relatedEntity).getTemplateAttributes());
		} else if (entityRecord.entity instanceof ContextSensor && relatedEntity instanceof TemplateSensor) {
			templateAttributes.addAll(((TemplateSensor) relatedEntity).getTemplateAttributes());
		}

		if (!templateAttributes.isEmpty()) {
			// hide Value containers that are missing in the template
			Set<String> names = new HashSet<>(entityRecord.core.getValues().keySet());
			names.remove(Entity.ATTR_NAME);
			names.remove(Entity.ATTR_MIMETYPE);
			templateAttributes.stream().map(Entity::getName).forEach(names::remove);
			entityRecord.core.hideValues(names);
		}
	}

	/**
	 * Loads all entities matching given {@link Filter} including all of related
	 * entities (optional, mandatory and children).
	 *
	 * @param filter The {@link Filter}.
	 * @return Returns the queried {@code EntityResult}.
	 * @throws DataAccessException Thrown if unable to load entities.
	 */
	protected EntityResult<T> load(Filter filter) throws DataAccessException {
		filtered = !filter.isEmtpty() || entityConfig.isReflexive();

		EntityType entityType = entityConfig.getEntityType();
		Relation reflexiveRelation = entityConfig.isReflexive() ? entityType.getRelation(entityType) : null;

		Query query = queryService.createQuery().selectAll(entityConfig.getEntityType());

		if (entityConfig.isReflexive()) {
			query.select(reflexiveRelation.getAttribute());
			// entities with children have to be processed before their
			// children!
			query.order(entityType.getIDAttribute());
		}

		// prepare relations select statements
		List<RelationConfig> optionalRelations = selectRelations(query, entityConfig.getOptionalConfigs(), false);
		List<RelationConfig> mandatoryRelations = selectRelations(query, entityConfig.getMandatoryConfigs(), true);

		// configure filter
		Filter adjustedFilter = Filter.or();
		if (filtered) {
			// preserve current conditions
			adjustedFilter.merge(filter);
			if (entityConfig.isReflexive()) {
				// extend to retrieve all reflexive child candidates
				adjustedFilter.add(ComparisonOperator.IS_NOT_NULL.create(reflexiveRelation.getAttribute(), 0L));
			}
		}

		// load entities and prepare mappings for required related entities
		List<EntityRecord<?>> parentRecords = new ArrayList<>();
		for (Record record : collectRecords(query.fetch(adjustedFilter))) {
			Optional<String> reflexiveParentID = Optional.empty();
			if (entityConfig.isReflexive()) {
				reflexiveParentID = record.getID(reflexiveRelation);
			}
			EntityRecord<T> entityRecord;

			if (entityConfig.isReflexive() && reflexiveParentID.isPresent()) {
				Optional<EntityRecord<T>> parentRecord = entityResult.get(reflexiveParentID.get());
				if (!parentRecord.isPresent()) {
					// this entity's parent was not loaded -> skip
					continue;
				}

				entityRecord = entityResult.add(parentRecord.get(), record);
				parentRecords.add(parentRecord.get());
			} else {
				entityRecord = entityResult.add(record);
			}

			// collect related instance IDs
			Stream.concat(optionalRelations.stream(), mandatoryRelations.stream())
					.forEach(rc -> rc.add(entityRecord, record));
		}

		if (entityResult.isEmpty()) {
			// no entities found -> neither related nor child entities required
			return entityResult;
		}

		// load and map related entities
		loadRelatedEntities(optionalRelations);
		loadRelatedEntities(mandatoryRelations);

		// sort children of parent
		if (entityConfig.isReflexive()) {
			@SuppressWarnings("unchecked")
			EntityConfig<Deletable> childConfig = (EntityConfig<Deletable>) entityConfig;
			for (EntityRecord<?> entityRecord : parentRecords) {
				entityRecord.core.getChildrenStore().sort(childConfig.getEntityClass(), childConfig.getComparator());
			}
		}

		// load children
		for (EntityConfig<? extends Deletable> childConfig : entityConfig.getChildConfigs()) {
			cache.add(new ChildRequest<>(this, childConfig).load());
		}

		return entityResult;
	}

}
