/********************************************************************************
 * Copyright (c) 2015-2020 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;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.asam.ods.AoException;
import org.asam.ods.ApplicationStructure;
import org.asam.ods.ElemId;
import org.asam.ods.InstanceElement;
import org.asam.ods.T_LONGLONG;
import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.Transaction;
import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.massdata.ReadRequest;
import org.eclipse.mdm.api.base.model.Channel;
import org.eclipse.mdm.api.base.model.ChannelGroup;
import org.eclipse.mdm.api.base.model.ContextDescribable;
import org.eclipse.mdm.api.base.model.ContextRoot;
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.base.model.MeasuredValues;
import org.eclipse.mdm.api.base.model.StatusAttachable;
import org.eclipse.mdm.api.base.model.Test;
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.model.User;
import org.eclipse.mdm.api.base.query.DataAccessException;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.query.JoinType;
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.EntityManager;
import org.eclipse.mdm.api.dflt.model.Classification;
import org.eclipse.mdm.api.dflt.model.Status;
import org.eclipse.mdm.api.dflt.model.TemplateTest;
import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
import org.eclipse.mdm.api.odsadapter.transaction.ODSTransaction;
import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
import org.eclipse.mdm.api.odsadapter.utils.ODSUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * ASAM ODS implementation of the {@link EntityManager} interface.
 *
 * @since 1.0.0
 * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
 */
public class ODSEntityManager implements EntityManager {

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

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

	// ======================================================================
	// Instance variables
	// ======================================================================
	private final Transfer transfer = Transfer.SOCKET;

	private final ODSContext context;
	private final ODSModelManager odsModelManager;
	private final QueryService queryService;
	private final EntityLoader entityLoader;

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

	/**
	 * Constructor.
	 *
	 * @param context The {@link ODSContext}.
	 */
	public ODSEntityManager(ODSContext context) {
		this.context = context;
		this.odsModelManager = context.getODSModelManager();
		this.queryService = context.getQueryService()
				.orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
		entityLoader = new EntityLoader(odsModelManager, queryService);
	}

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

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Environment loadEnvironment() throws DataAccessException {
		List<Environment> environments = loadAll(Environment.class);
		if (environments.size() != 1) {
			throw new DataAccessException("Unable to laod the environment entity.");
		}

		return environments.get(0);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Optional<User> loadLoggedOnUser() throws DataAccessException {
		InstanceElement ieUser = null;
		try {
			ieUser = odsModelManager.getAoSession().getUser();
			return Optional.of(
					entityLoader.load(new Key<>(User.class), Long.toString(ODSConverter.fromODSLong(ieUser.getId()))));
		} catch (AoException e) {
			throw new DataAccessException("Unable to load the logged in user entity due to: " + e.reason, e);
		} finally {
			try {
				if (ieUser != null) {
					ieUser.destroy();
					ieUser._release();
				}
			} catch (AoException aoe) {
				LOGGER.warn("Unable to destroy the CORBA resource due to: " + aoe.reason, aoe);
				ieUser._release();
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> List<T> load(Class<T> entityClass, Collection<String> instanceIDs)
			throws DataAccessException {
		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> List<T> load(Class<T> entityClass, ContextType contextType,
			Collection<String> instanceIDs) throws DataAccessException {
		return entityLoader.loadAll(new Key<>(entityClass, contextType), instanceIDs);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> Optional<T> loadParent(Entity child, Class<T> entityClass) throws DataAccessException {
		EntityType parentEntityType = odsModelManager.getEntityType(entityClass);
		EntityType childEntityType = odsModelManager.getEntityType(child);
		Query query = queryService.createQuery().selectID(parentEntityType);

		if (child instanceof Channel && ChannelGroup.class.equals(entityClass)) {
			// this covers the gap between channel and channel group via local
			// column
			EntityType localColumnEntityType = odsModelManager.getEntityType("LocalColumn");
			query.join(childEntityType, localColumnEntityType).join(localColumnEntityType, parentEntityType);
		} else {
			query.join(childEntityType, parentEntityType);
		}

		Optional<String> instanceID = query.fetchSingleton(Filter.idOnly(childEntityType, child.getID()))
				.map(r -> r.getRecord(parentEntityType)).map(Record::getID);
		if (instanceID.isPresent()) {
			return Optional.of(entityLoader.load(new Key<>(entityClass), instanceID.get()));
		}

		return Optional.empty();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> List<T> loadAll(Class<T> entityClass, String pattern) throws DataAccessException {
		return entityLoader.loadAll(new Key<>(entityClass), pattern);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends StatusAttachable> List<T> loadAll(Class<T> entityClass, Status status, String pattern)
			throws DataAccessException {
		EntityType entityType = odsModelManager.getEntityType(entityClass);
		EntityType classificationType = odsModelManager.getEntityType(Classification.class);
		EntityType statusEntityType = odsModelManager.getEntityType(status.getTypeName());

		List<String> instanceIDs = queryService.createQuery().join(entityType, classificationType)
				.join(classificationType, statusEntityType).selectID(entityType)
				.fetch(Filter.and().id(statusEntityType, status.getID()).name(entityType, pattern)).stream()
				.map(r -> r.getRecord(entityType)).map(Record::getID).collect(Collectors.toList());

		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
	}

	/*
	 * @Override public List<Status> loadAllStatus(Class<? extends StatusAttachable>
	 * entityClass, String pattern) throws DataAccessException { return
	 * entityLoader.loadAll(new Key<>(Status.class, entityClass), pattern); }
	 */

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> List<T> loadAll(Class<T> entityClass, ContextType contextType, String pattern)
			throws DataAccessException {
		return entityLoader.loadAll(new Key<>(entityClass, contextType), pattern);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public <T extends Entity> List<T> loadChildren(Entity parent, Class<T> entityClass, String pattern)
			throws DataAccessException {
		EntityType parentEntityType = odsModelManager.getEntityType(parent);
		EntityType childEntityType = odsModelManager.getEntityType(entityClass);
		Query query = queryService.createQuery();

		if (parent instanceof ChannelGroup && Channel.class.equals(entityClass)) {
			// this covers the gap between channel and channel group via local
			// column
			EntityType localColumnEntityType = odsModelManager.getEntityType("LocalColumn");
			query.join(childEntityType, localColumnEntityType).join(localColumnEntityType, parentEntityType);
		} else {
			query.join(childEntityType, parentEntityType);
		}

		List<String> instanceIDs = query.selectID(childEntityType)
				.fetch(Filter.and().id(parentEntityType, parent.getID()).name(childEntityType, pattern)).stream()
				.map(r -> r.getRecord(childEntityType)).map(Record::getID).collect(Collectors.toList());
		return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
	}

	// /**
	// * {@inheritDoc}
	// */
	// @Override
	// public <T extends StatusAttachable> List<T> loadChildren(Entity parent,
	// Class<T> entityClass, Status status,
	// String pattern) throws DataAccessException {
	// EntityType parentEntityType = modelManager.getEntityType(parent);
	// EntityType childEntityType = modelManager.getEntityType(entityClass);
	// EntityType statusEntityType =
	// modelManager.getEntityType(status.getTypeName());
	//
	// List<String> instanceIDs = modelManager.createQuery()
	// .join(childEntityType, parentEntityType, statusEntityType)
	// .selectID(childEntityType)
	// .fetch(Filter.and()
	// .id(parentEntityType, parent.getID())
	// .id(statusEntityType, status.getID())
	// .name(childEntityType, pattern))
	// .stream().map(r ->
	// r.getRecord(childEntityType)).map(Record::getID).collect(Collectors.toList());
	//
	// return entityLoader.loadAll(new Key<>(entityClass), instanceIDs);
	// }

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<ContextType> loadContextTypes(ContextDescribable contextDescribable) throws DataAccessException {
		EntityType contextDescribableEntityType = odsModelManager.getEntityType(contextDescribable);
		Query query = queryService.createQuery();

		Map<ContextType, EntityType> contextRootEntityTypes = new EnumMap<>(ContextType.class);
		for (ContextType contextType : ContextType.values()) {
			EntityType entityType = odsModelManager.getEntityType(ContextRoot.class, contextType);
			contextRootEntityTypes.put(contextType, entityType);
			query.join(contextDescribableEntityType.getRelation(entityType), JoinType.OUTER).selectID(entityType);
		}

		Optional<Result> result = query
				.fetchSingleton(Filter.idOnly(contextDescribableEntityType, contextDescribable.getID()));
		if (result.isPresent()) {
			List<ContextType> contextTypes = new ArrayList<>();
			for (Entry<ContextType, EntityType> entry : contextRootEntityTypes.entrySet()) {
				Optional<String> instanceID = result.map(r -> r.getRecord(entry.getValue())).map(Record::getID);
				if (instanceID.isPresent()) {
					contextTypes.add(entry.getKey());
				}
			}

			return contextTypes;
		}

		return Collections.emptyList();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Map<ContextType, ContextRoot> loadContexts(ContextDescribable contextDescribable,
			ContextType... contextTypes) throws DataAccessException {
		EntityType contextDescribableEntityType = odsModelManager.getEntityType(contextDescribable);
		Query query = queryService.createQuery();

		Map<ContextType, EntityType> contextRootEntityTypes = new EnumMap<>(ContextType.class);
		for (ContextType contextType : contextTypes.length == 0 ? ContextType.values() : contextTypes) {
			EntityType entityType = odsModelManager.getEntityType(ContextRoot.class, contextType);
			contextRootEntityTypes.put(contextType, entityType);
			query.join(contextDescribableEntityType.getRelation(entityType), JoinType.OUTER).selectID(entityType);
		}

		Optional<Result> result = query
				.fetchSingleton(Filter.idOnly(contextDescribableEntityType, contextDescribable.getID()));
		if (result.isPresent()) {
			Map<ContextType, ContextRoot> contextRoots = new EnumMap<>(ContextType.class);
			for (Entry<ContextType, EntityType> entry : contextRootEntityTypes.entrySet()) {
				String instanceID = result.get().getRecord(entry.getValue()).getID();
				if (ODSUtils.isValidID(instanceID)) {
					contextRoots.put(entry.getKey(),
							entityLoader.load(new Key<>(ContextRoot.class, entry.getKey()), instanceID));
				}
			}

			return contextRoots;
		}

		return Collections.emptyMap();
	}

	/**
	 * {@inheritDoc}
	 */
	public <T extends Entity> List<T> loadRelatedEntities(Entity entity, String relationName, Class<T> relatedClass) {
		ODSEntityType entityType = ((ODSEntityType) context.getODSModelManager().getEntityType(entity));
		ElemId elemId = new ElemId(entityType.getODSID(), ODSConverter.toODSID(entity.getID()));

		try {
			T_LONGLONG[] instanceIds = context.getAoSession().getApplElemAccess().getRelInst(elemId, relationName);
			List<String> instanceIDs = Stream.of(instanceIds).map(ODSConverter::fromODSLong).map(l -> l.toString())
					.collect(Collectors.toList());
			return entityLoader.loadAll(new Key<>(relatedClass), instanceIDs);
		} catch (AoException e) {
			throw new DataAccessException("" + e.reason, e); // TODO
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<MeasuredValues> readMeasuredValues(ReadRequest readRequest) throws DataAccessException {
		return new ReadRequestHandler(odsModelManager, queryService).execute(readRequest);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Transaction startTransaction() throws DataAccessException {
		try {
			return new ODSTransaction(context, loadEnvironment(), transfer);
		} catch (AoException e) {
			throw new DataAccessException("Unable to start transaction due to: " + e.reason, e);
		}
	}

	/**
	 * Retrives the ASAM paths for the given entities. The ASAM paths are prefixed
	 * with a servicename, in the form
	 * <code>corbaloc:[iop|ssliop]:1.2@HOSTNAME:PORT/NameService/MDM.ASAM-ODS/</code>
	 * 
	 * @returns returns a map with the ASAM paths to the given entities. If a entity
	 *          is not found in the ODS server the entity is not included in the
	 *          result map.
	 * @throws DataAccessException      if links could not be loaded for the given
	 *                                  entities
	 * @throws IllegalArgumentException if a the source or typeName of an entity is
	 *                                  invalid
	 * @see org.eclipse.mdm.api.base.BaseEntityManager#getLinks(Collection)
	 */
	@Override
	public Map<Entity, String> getLinks(Collection<Entity> entities) throws DataAccessException {

		Map<Entity, String> linkMap = new HashMap<>();

		ApplicationStructure appStructure;
		try {
			appStructure = odsModelManager.getAoSession().getApplicationStructure();
		} catch (AoException e) {
			throw new DataAccessException("Could not load application structure! Reason: " + e.reason, e);
		}

		String serverRoot = context.getParameters().get(ODSContextFactory.PARAM_NAMESERVICE) + "/"
				+ context.getParameters().get(ODSContextFactory.PARAM_SERVICENAME);

		Map<String, List<Entity>> entitiesByTypeName = entities.stream().filter(e -> e.getTypeName() != null)
				.collect(Collectors.groupingBy(Entity::getTypeName));

		for (Map.Entry<String, List<Entity>> entry : entitiesByTypeName.entrySet()) {
			ODSEntityType et = (ODSEntityType) odsModelManager.getEntityType(entry.getKey());

			List<ElemId> elemIds = entry.getValue().stream()
					.map(e -> new ElemId(et.getODSID(), ODSConverter.toODSLong(Long.parseLong(e.getID()))))
					.collect(Collectors.toList());

			try {
				InstanceElement[] instances = appStructure.getInstancesById(elemIds.toArray(new ElemId[0]));

				for (InstanceElement ie : instances) {
					String id = Long.toString(ODSConverter.fromODSLong(ie.getId()));
					String asamPath = serverRoot + ie.getAsamPath();
					entry.getValue().stream().filter(e -> e.getID().equals(id)).findFirst()
							.ifPresent(e -> linkMap.put(e, asamPath));
				}
			} catch (AoException e) {
				LOGGER.debug("Could not load links for entities: " + entities + ". Reason: " + e.reason, e);
			}
		}

		return linkMap;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Optional<TemplateTest> loadTemplate(Test test) {
		return Optional.ofNullable(ODSEntityFactory.extract(test).getMutableStore().get(TemplateTest.class));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Optional<TemplateTestStep> loadTemplate(TestStep testStep) {
		return Optional.ofNullable(ODSEntityFactory.extract(testStep).getMutableStore().get(TemplateTestStep.class));
	}
}
