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

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.Transaction;
import org.eclipse.mdm.api.base.adapter.ModelManager;
import org.eclipse.mdm.api.base.massdata.AnyTypeValuesBuilder;
import org.eclipse.mdm.api.base.massdata.ComplexNumericalValuesBuilder;
import org.eclipse.mdm.api.base.massdata.NumericalValuesBuilder;
import org.eclipse.mdm.api.base.massdata.WriteRequest;
import org.eclipse.mdm.api.base.massdata.WriteRequestBuilder;
import org.eclipse.mdm.api.base.model.Channel;
import org.eclipse.mdm.api.base.model.ChannelGroup;
import org.eclipse.mdm.api.base.model.DoubleComplex;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.FileLink;
import org.eclipse.mdm.api.base.model.FloatComplex;
import org.eclipse.mdm.api.base.model.MeasuredValues;
import org.eclipse.mdm.api.base.model.MeasuredValues.ValueIterator;
import org.eclipse.mdm.api.base.model.Measurement;
import org.eclipse.mdm.api.base.model.ScalarType;
import org.eclipse.mdm.api.base.model.SequenceRepresentation;
import org.eclipse.mdm.api.base.model.Test;
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.search.SearchService;
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.Pool;
import org.eclipse.mdm.api.dflt.model.Project;

import com.google.common.base.Strings;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;

public abstract class AtfxTransferBase {
	List<Class<? extends Entity>> supportedRootEntities = Arrays.asList(Project.class, Pool.class, Test.class,
			TestStep.class, Measurement.class);

	ApplicationContext contextSrc;
	EntityManager entityManagerSrc;

	ApplicationContext contextDst;
	EntityManager entityManagerDst;
	EntityFactory entityFactoryDst;
	ModelManager modelManagerDst;

	Map<EntityHolder, EntityHolder> mapSrcDstEntities = new HashMap<>();

	public AtfxTransferBase(ApplicationContext src, ApplicationContext dst) {
		contextSrc = src;
		entityManagerSrc = contextSrc.getEntityManager()
				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));

		contextDst = dst;
		entityManagerDst = contextDst.getEntityManager()
				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
		entityFactoryDst = contextDst.getEntityFactory()
				.orElseThrow(() -> new ServiceNotProvidedException(EntityFactory.class));
		modelManagerDst = contextDst.getModelManager()
				.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
	}

	ListMultimap<Class<? extends Entity>, Entity> loadParents(List<? extends Entity> entities) {
		List<Entity> list = entities.stream().filter(e -> !isSupported(e)).collect(Collectors.toList());
		if (!list.isEmpty()) {
			throw new ApiCopyException("Entity " + list + " not supported!");
		}
		LinkedListMultimap<Class<? extends Entity>, Entity> byType = LinkedListMultimap.create();
		entities.forEach(e -> byType.put(e.getClass(), e));

		byType.get(Measurement.class)
				.forEach(e -> byType.put(TestStep.class, entityManagerSrc.loadParent(e, TestStep.class).get()));
		byType.get(TestStep.class)
				.forEach(e -> byType.put(Test.class, entityManagerSrc.loadParent(e, Test.class).get()));
		byType.get(Test.class).forEach(e -> byType.put(Pool.class, entityManagerSrc.loadParent(e, Pool.class).get()));
		byType.get(Pool.class)
				.forEach(e -> byType.put(Project.class, entityManagerSrc.loadParent(e, Project.class).get()));

		entities.forEach(e -> byType.remove(e.getClass(), e));
		return byType;
	}

	boolean isSupported(Entity e) {
		return supportedRootEntities.contains(e.getClass());
	}

	<T extends Entity> Optional<T> fetchOne(SearchService searchService, Class<T> entityClass, Filter filter) {
		List<T> results = searchService.fetch(entityClass, filter);

		if (results.isEmpty()) {
			return Optional.empty();
		} else if (results.size() == 1) {
			return Optional.of(results.get(0));
		} else {
			throw new IllegalStateException(String.format("Expected at most one instance of %s, but found %s!",
					entityClass.getName(), results.size()));
		}
	}

	<T extends Entity> Optional<T> fetchOne(EntityManager entityManager, Class<T> entityClass, String name) {
		List<T> results = entityManager.loadAll(entityClass).stream().filter(entity -> entity.getName().equals(name))
				.collect(Collectors.toList());

		if (results.isEmpty()) {
			return Optional.empty();
		} else if (results.size() == 1) {
			return Optional.of(results.get(0));
		} else {
			throw new IllegalStateException(String.format("Expected at most one instance of %s, but found %s!",
					entityClass.getName(), results.size()));
		}
	}

	boolean isNewEntity(Entity entity) {
		return (Strings.isNullOrEmpty(entity.getID()) || Long.valueOf(entity.getID()) <= 0);
	}

	void persist(Transaction transaction, Entity entity) {
		if (isNewEntity(entity)) {
			transaction.create(Lists.newArrayList(entity));
		} else {
			transaction.update(Lists.newArrayList(entity));
		}
	}

	void copyValues(Entity srcEntity, Entity dstEntity, List<String> ignoredAttributes) {
		Set<String> valueNamesDst = dstEntity.getValues().keySet();
		for (Map.Entry<String, Value> me : srcEntity.getValues().entrySet()) {
			String key = me.getKey();
			if (!ignoredAttributes.contains(key) && valueNamesDst.contains(key)) {
				dstEntity.getValue(me.getKey()).set(me.getValue().extract());
			}
		}
	}

	WriteRequest createWriteRequest(ChannelGroup channelGroupDst, Channel channelDst, MeasuredValues measuredValues) {
		WriteRequestBuilder wrb = WriteRequest.create(channelGroupDst, channelDst, measuredValues.getAxisType());
		NumericalValuesBuilder builder = null;
		SequenceRepresentation seqRep = measuredValues.getSequenceRepresentation();
		ScalarType scalarType = measuredValues.getScalarType();
		boolean independent = measuredValues.isIndependent();
		double[] generationParameters = measuredValues.getGenerationParameters();

		if (SequenceRepresentation.EXPLICIT.equals(seqRep) || SequenceRepresentation.EXPLICIT_EXTERNAL.equals(seqRep)) {
			builder = wrb.explicit();
		} else if (SequenceRepresentation.IMPLICIT_CONSTANT.equals(seqRep)) {
			checkGenerationParameters(generationParameters, 1);

			return wrb.implicitConstant(scalarType, generationParameters[0]).build();
		} else if (SequenceRepresentation.IMPLICIT_LINEAR.equals(seqRep)) {
			checkGenerationParameters(generationParameters, 2);

			return wrb.implicitLinear(scalarType, generationParameters[0], generationParameters[1])
					.independent(independent).build();
		} else if (SequenceRepresentation.IMPLICIT_SAW.equals(seqRep)) {
			checkGenerationParameters(generationParameters, 3);

			return wrb
					.implicitSaw(scalarType, generationParameters[0], generationParameters[1], generationParameters[2])
					.build();
		} else if (SequenceRepresentation.RAW_LINEAR.equals(seqRep)
				|| SequenceRepresentation.RAW_LINEAR_EXTERNAL.equals(seqRep)) {
			checkGenerationParameters(generationParameters, 2);

			builder = wrb.rawLinear(generationParameters[0], generationParameters[1]);
		} else if (SequenceRepresentation.RAW_LINEAR_CALIBRATED.equals(seqRep)
				|| SequenceRepresentation.RAW_LINEAR_CALIBRATED_EXTERNAL.equals(seqRep)) {
			checkGenerationParameters(generationParameters, 3);

			builder = wrb.rawLinearCalibrated(generationParameters[0], generationParameters[1],
					generationParameters[2]);
		} else if (SequenceRepresentation.RAW_POLYNOMIAL.equals(seqRep)
				|| SequenceRepresentation.RAW_POLYNOMIAL_EXTERNAL.equals(seqRep)) {
			builder = wrb.rawPolynomial(generationParameters);
		}

		if (scalarType.isString()) {
			String[] values = new String[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<String> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).stringValues(values, flags).build();
		} else if (scalarType.isDate()) {
			LocalDateTime[] values = new LocalDateTime[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<LocalDateTime> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).dateValues(values, flags).independent(independent)
					.build();
		} else if (scalarType.isBoolean()) {
			boolean[] values = new boolean[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Boolean> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).booleanValues(values, flags).build();
		} else if (scalarType.isByte()) {
			byte[] values = new byte[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Byte> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.byteValues(values, flags).independent(independent).build();
		} else if (scalarType.isShort()) {
			short[] values = new short[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Short> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.shortValues(values, flags).independent(independent).build();
		} else if (scalarType.isInteger()) {
			int[] values = new int[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Integer> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.integerValues(values, flags).independent(independent).build();
		} else if (scalarType.isLong()) {
			long[] values = new long[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Long> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.longValues(values, flags).independent(independent).build();
		} else if (scalarType.isFloat()) {
			float[] values = new float[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Float> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.floatValues(values, flags).independent(independent).build();
		} else if (scalarType.isDouble()) {
			double[] values = new double[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<Double> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return builder.doubleValues(values, flags).independent(independent).build();
		} else if (scalarType.isByteStream()) {
			byte[][] values = new byte[measuredValues.getLength()][];
			boolean[] flags = new boolean[values.length];
			ValueIterator<byte[]> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).byteStreamValues(values, flags).build();
		} else if (scalarType.isFloatComplex()) {
			FloatComplex[] values = new FloatComplex[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<FloatComplex> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, ComplexNumericalValuesBuilder.class).floatComplexValues(values, flags).build();
		} else if (scalarType.isDoubleComplex()) {
			DoubleComplex[] values = new DoubleComplex[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<DoubleComplex> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, ComplexNumericalValuesBuilder.class).doubleComplexValues(values, flags).build();
		} else if (scalarType.isFileLink()) {
			FileLink[] values = new FileLink[measuredValues.getLength()];
			boolean[] flags = new boolean[values.length];
			ValueIterator<FileLink> iter = measuredValues.iterator();
			int count = 0;
			while (iter.hasNext()) {
				flags[count] = iter.isValid();
				values[count++] = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).fileLinkValues(values, flags).build();
		} else if (scalarType.isBlob()) {
			Object value = null;
			ValueIterator<Object> iter = measuredValues.iterator();
			while (iter.hasNext()) {
				value = iter.next();
			}

			return castBuilder(builder, AnyTypeValuesBuilder.class).blobValue(value).build();
		} else {
			throw new IllegalStateException(
					String.format("Unsupported ScalarType %s in MeasuredValues!", scalarType.name()));
		}
	}

	void checkGenerationParameters(double[] generationParameters, int expectedLength) {
		if (null == generationParameters || generationParameters.length < expectedLength) {
			throw new IllegalStateException(String.format("Number of generation parameters is %d, expected %d!",
					(null == generationParameters ? 0 : generationParameters.length), expectedLength));
		}
	}

	<T extends NumericalValuesBuilder> T castBuilder(NumericalValuesBuilder builder, Class<T> cls) {
		if (!cls.isInstance(builder)) {
			throw new IllegalStateException(String.format(
					"Error creating the write values builder, expected class is %s, actual class is %s (likely column data type and sequence representation mismatch)!",
					cls.getName(), (null == builder ? "???" : builder.getClass().getName())));
		}

		return cls.cast(builder);
	}

}
