/********************************************************************************
 * 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.boundary.integrationtest;

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.tuple;
import static org.hamcrest.Matchers.equalTo;

import java.util.Arrays;
import java.util.Comparator;
import java.util.EnumSet;
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.IntStream;

import javax.ws.rs.core.Response.Status;

import org.assertj.core.api.SoftAssertions;
import org.assertj.core.groups.Tuple;
import org.eclipse.mdm.businessobjects.boundary.ResourceConstants;
import org.eclipse.mdm.protobuf.Mdm;
import org.eclipse.mdm.protobuf.Mdm.AxisType;
import org.eclipse.mdm.protobuf.Mdm.BooleanArray;
import org.eclipse.mdm.protobuf.Mdm.ByteArray;
import org.eclipse.mdm.protobuf.Mdm.ByteStreamArray;
import org.eclipse.mdm.protobuf.Mdm.DateArray;
import org.eclipse.mdm.protobuf.Mdm.DoubleArray;
import org.eclipse.mdm.protobuf.Mdm.DoubleComplex;
import org.eclipse.mdm.protobuf.Mdm.DoubleComplexArray;
import org.eclipse.mdm.protobuf.Mdm.FloatArray;
import org.eclipse.mdm.protobuf.Mdm.FloatComplex;
import org.eclipse.mdm.protobuf.Mdm.FloatComplexArray;
import org.eclipse.mdm.protobuf.Mdm.IntegerArray;
import org.eclipse.mdm.protobuf.Mdm.LongArray;
import org.eclipse.mdm.protobuf.Mdm.MeasuredValues;
import org.eclipse.mdm.protobuf.Mdm.MeasuredValuesList;
import org.eclipse.mdm.protobuf.Mdm.ScalarType;
import org.eclipse.mdm.protobuf.Mdm.ShortArray;
import org.eclipse.mdm.protobuf.Mdm.StringArray;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.DataCase;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.ExplicitData;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.ImplicitConstant;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.ImplicitLinear;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.ImplicitSaw;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.RawLinear;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.RawLinearCalibrated;
import org.eclipse.mdm.protobuf.Mdm.WriteRequestList.WriteRequest.RawPolynomial;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.primitives.Booleans;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Floats;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;

import io.restassured.http.ContentType;
import io.restassured.response.ExtractableResponse;

/**
 * Test class for {@ChannelResource}.
 * 
 * @author Johannes Stamm, Peak Solution GmbH Nuernberg
 * @see EntityResourceIntegrationTest
 *
 */
public class ValuesResourceIntegrationTest extends ResourceIntegrationTest {

	public static final EnumSet<ScalarType> scalarTypes = EnumSet.of(ScalarType.STRING, ScalarType.DATE,
			ScalarType.BOOLEAN, ScalarType.BYTE, ScalarType.SHORT, ScalarType.INTEGER, ScalarType.LONG,
			ScalarType.FLOAT, ScalarType.DOUBLE, ScalarType.BYTE_STREAM, ScalarType.FLOAT_COMPLEX,
			ScalarType.DOUBLE_COMPLEX);

	private static final List<Boolean> SCALARTYPE_BOOLEAN = Booleans.asList(true, false, true);
	private static final ByteString SCALARTYPE_BYTES = ByteString
			.copyFrom(new byte[] { (byte) 0x01, (byte) 0xFF, (byte) 0xF1 });
	private static final List<Integer> SCALARTYPE_SHORTS = Ints.asList(12, 13, 14);
	private static final List<Integer> SCALARTYPE_INTEGER = Ints.asList(12, 13, 14);
	private static final List<Long> SCALARTYPE_LONG = Longs.asList(12L, 13L, 14L);
	private static final List<Float> SCALARTYPE_FLOAT = Floats.asList(12f, 13f, 14f);
	private static final List<Double> SCALARTYPE_DOUBLE = Doubles.asList(12.0, 13.0, 14.0);
	private static final List<FloatComplex> SCALARTYPE_FLOAT_COMPLEX = Arrays.asList(
			FloatComplex.newBuilder().setRe(12f).setIm(11f).build(),
			FloatComplex.newBuilder().setRe(13f).setIm(10f).build(),
			FloatComplex.newBuilder().setRe(14f).setIm(9f).build());
	private static final List<DoubleComplex> SCALARTYPE_DOUBLE_COMPLEX = Arrays.asList(
			DoubleComplex.newBuilder().setRe(12.0).setIm(11.0).build(),
			DoubleComplex.newBuilder().setRe(13.0).setIm(10.0).build(),
			DoubleComplex.newBuilder().setRe(14.0).setIm(9.0).build());
	private static final List<ByteString> SCALARTYPE_BYTE_STREAM = Arrays.asList(
			ByteString.copyFrom(new byte[] { (byte) 12, (byte) 11 }),
			ByteString.copyFrom(new byte[] { (byte) 13, (byte) 10 }),
			ByteString.copyFrom(new byte[] { (byte) 14, (byte) 9 }));
	private static final List<String> SCALARTYPE_STRING = Arrays.asList("one", "two", "three");
	private static final List<Timestamp> SCALARTYPE_DATE = Arrays.asList(Timestamps.fromMillis(1546300800000L),
			Timestamps.fromMillis(1546400800000L), Timestamps.fromMillis(1546500800000L));
	private static final List<Boolean> SCALARTYPE_FLAGS = Booleans.asList(true, true, true);

	private static final String MIMETYPE_APPLICATION_PROTOBUF = "application/protobuf";

	private static final Logger LOGGER = LoggerFactory.getLogger(ValuesResourceIntegrationTest.class);

	private static final int LENGTH = 5;

	private static final List<Integer> INTS = IntStream.range(0, LENGTH)
			.map(i -> (int) (10 * Math.sin((double) i / LENGTH * Math.PI))).boxed().collect(Collectors.toList());

	private static final List<Double> DOUBLES = IntStream.range(0, LENGTH)
			.mapToDouble(i -> 10 * Math.sin((double) i / LENGTH * Math.PI)).boxed().collect(Collectors.toList());

	private static final ExplicitData INT_DATA = ExplicitData.newBuilder()
			.setIntegerArray(IntegerArray.newBuilder().addAllValues(INTS)).build();

	private static final ExplicitData DOUBLE_DATA = ExplicitData.newBuilder()
			.setDoubleArray(DoubleArray.newBuilder().addAllValues(DOUBLES)).build();

	private static List<Boolean> FLAGS;

	@BeforeClass
	public static void prepareTestData() {
		LOGGER.debug("Preparing ValuesResourceIntegrationTest");

		boolean[] flagsArray = new boolean[LENGTH];
		Arrays.fill(flagsArray, true);
		FLAGS = Booleans.asList(flagsArray);

		// prepare test data for creating the parent Measurement
		MeasurementResourceIntegrationTest.prepareTestData();
		MeasurementResourceIntegrationTest.createEntity();
		// prepare test data for creating Quantity
		QuantityResourceIntegrationTest.prepareTestData();
		QuantityResourceIntegrationTest.createEntity();
	}

	@Test
	public void testAllDataSeqReps() throws InvalidProtocolBufferException {

		String channelGroupId = createChannelGroup();

		Map<String, DataCase> dataCaseChannelIds = createChannelsForDataCase();

		writeValuesAllSequenceRepresentations(channelGroupId, dataCaseChannelIds);

		// read MeasuredValues
		Mdm.ReadRequest readRequest = Mdm.ReadRequest.newBuilder().setChannelGroupId(channelGroupId).build();

		ExtractableResponse<io.restassured.response.Response> response = given()
				.contentType(MIMETYPE_APPLICATION_PROTOBUF).body(readRequest.toByteArray()).post("/values/read").then()
				.log().ifError().contentType(MIMETYPE_APPLICATION_PROTOBUF).statusCode(200).extract();

		Mdm.MeasuredValuesList mvl = Mdm.MeasuredValuesList.parseFrom(response.asByteArray());

		SoftAssertions softly = new SoftAssertions();
		assertExplicit(softly, mvl);
		assertImplicitConstant(softly, mvl);
		assertImplicitLinear(softly, mvl);
		assertImplicitSaw(softly, mvl);
		assertRawLinear(softly, mvl);
		assertRawPolynomial(softly, mvl);
		assertRawLinearCalibrated(softly, mvl);
		softly.assertAll();

		// read preview values
		int chunkSize = 2;

		Mdm.PreviewRequest previewRequest = Mdm.PreviewRequest.newBuilder()
				.setReadRequest(Mdm.ReadRequest.newBuilder().setChannelGroupId(channelGroupId))
				.setNumberOfChunks(chunkSize).build();

		ExtractableResponse<io.restassured.response.Response> previewResponse = given()
				.contentType(MIMETYPE_APPLICATION_PROTOBUF).body(previewRequest.toByteArray()).post("/values/preview")
				.then().log().ifError().contentType(MIMETYPE_APPLICATION_PROTOBUF).statusCode(200).extract();

		Mdm.PreviewValuesList pvl = Mdm.PreviewValuesList.parseFrom(previewResponse.asByteArray());

		List<String> channelNames = Arrays.asList("Channel_EXPLICIT", "Channel_IMPLICIT_CONSTANT",
				"Channel_IMPLICIT_LINEAR", "Channel_IMPLICIT_SAW", "Channel_RAW_LINEAR",
				"Channel_RAW_LINEAR_CALIBRATED", "Channel_RAW_POLYNOMIAL");

		SoftAssertions softly2 = new SoftAssertions();
		softly2.assertThat(pvl.getAvgList()).extracting(MeasuredValues::getName).containsAll(channelNames);
		softly2.assertThat(pvl.getMinList()).extracting(MeasuredValues::getName).containsAll(channelNames);
		softly2.assertThat(pvl.getMaxList()).extracting(MeasuredValues::getName).containsAll(channelNames);

		softly2.assertThat(pvl.getAvgList()).extracting(mv -> mv.getDoubleArray().getValuesCount())
				.containsOnly(chunkSize);
		softly2.assertThat(pvl.getMinList()).extracting(mv -> mv.getDoubleArray().getValuesCount())
				.containsOnly(chunkSize);
		softly2.assertThat(pvl.getMaxList()).extracting(mv -> mv.getDoubleArray().getValuesCount())
				.containsOnly(chunkSize);
		softly2.assertAll();
	}

	@Test
	public void testAllScalarTypes() throws InvalidProtocolBufferException {

		String channelGroupId = createChannelGroup();

		Map<String, ScalarType> scalarTypeChannelIds = createChannelsForScalarTypes();

		writeValuesAllScalarTypes(channelGroupId, scalarTypeChannelIds);

		// read MeasuredValues
		Mdm.ReadRequest readRequest = Mdm.ReadRequest.newBuilder().setChannelGroupId(channelGroupId).build();

		ExtractableResponse<io.restassured.response.Response> response = given()
				.contentType(MIMETYPE_APPLICATION_PROTOBUF).body(readRequest.toByteArray()).post("/values/read").then()
				.log().ifError().contentType(MIMETYPE_APPLICATION_PROTOBUF).statusCode(200).extract();

		Mdm.MeasuredValuesList mvl = Mdm.MeasuredValuesList.parseFrom(response.asByteArray());

		SoftAssertions softly = new SoftAssertions();
		assertBoolean(softly, mvl);
		assertByte(softly, mvl);
		assertShort(softly, mvl);
		assertInteger(softly, mvl);
		assertLong(softly, mvl);
		assertFloat(softly, mvl);
		assertDouble(softly, mvl);
		assertFloatComplex(softly, mvl);
		assertDoubleComplex(softly, mvl);
		assertByteStream(softly, mvl);
		assertString(softly, mvl);
		assertDate(softly, mvl);
		softly.assertAll();

		// read preview values
		int chunkSize = 2;

		Mdm.PreviewRequest previewRequest = Mdm.PreviewRequest.newBuilder()
				.setReadRequest(Mdm.ReadRequest.newBuilder().setChannelGroupId(channelGroupId))
				.setNumberOfChunks(chunkSize).build();

		ExtractableResponse<io.restassured.response.Response> previewResponse = given()
				.contentType(MIMETYPE_APPLICATION_PROTOBUF).body(previewRequest.toByteArray()).post("/values/preview")
				.then().log().ifError().contentType(MIMETYPE_APPLICATION_PROTOBUF).statusCode(200).extract();

		Mdm.PreviewValuesList pvl = Mdm.PreviewValuesList.parseFrom(previewResponse.asByteArray());

		Tuple[] previewChannelNames = new Tuple[] { tuple("Channel_BYTE", 2), tuple("Channel_SHORT", 2),
				tuple("Channel_INTEGER", 2), tuple("Channel_LONG", 2), tuple("Channel_FLOAT", 2),
				tuple("Channel_DOUBLE", 2), tuple("Channel_FLOAT_COMPLEX", 0), tuple("Channel_DOUBLE_COMPLEX", 0),
				tuple("Channel_BOOLEAN", 0), tuple("Channel_STRING", 0), tuple("Channel_BYTE_STREAM", 0),
				tuple("Channel_DATE", 0) };

		SoftAssertions softly2 = new SoftAssertions();
		softly2.assertThat(pvl.getAvgList()).extracting(mv -> tuple(mv.getName(), mv.getDoubleArray().getValuesCount()))
				.containsOnly(previewChannelNames);
		softly2.assertThat(pvl.getMinList()).extracting(mv -> tuple(mv.getName(), mv.getDoubleArray().getValuesCount()))
				.containsOnly(previewChannelNames);
		softly2.assertThat(pvl.getMaxList()).extracting(mv -> tuple(mv.getName(), mv.getDoubleArray().getValuesCount()))
				.containsOnly(previewChannelNames);

		// Date will return a DateArray instead of a DoubleArray
		softly2.assertThat(pvl.getAvgList()).extracting(mv -> tuple(mv.getName(), mv.getDateArray().getValuesCount()))
				.contains(tuple("Channel_DATE", 2));
		softly2.assertThat(pvl.getMinList()).extracting(mv -> tuple(mv.getName(), mv.getDateArray().getValuesCount()))
				.contains(tuple("Channel_DATE", 2));
		softly2.assertThat(pvl.getMaxList()).extracting(mv -> tuple(mv.getName(), mv.getDateArray().getValuesCount()))
				.contains(tuple("Channel_DATE", 2));

		softly2.assertAll();
	}

	private void writeValuesAllSequenceRepresentations(String channelGroupId, Map<String, DataCase> channelIds) {
		// write MeasuredValues
		WriteRequestList.Builder writeRequestList = WriteRequestList.newBuilder();

		for (Map.Entry<String, DataCase> entry : channelIds.entrySet()) {
			WriteRequest.Builder builder = WriteRequest.newBuilder().setChannelGroupId(channelGroupId)
					.setChannelId(entry.getKey()).setAxisTypeValue(AxisType.XY_AXIS_VALUE).setIndependent(false);
			switch (entry.getValue()) {
			case EXPLICIT:
				builder.setExplicit(INT_DATA);
				break;
			case IMPLICIT_CONSTANT:
				builder.setImplicitConstant(
						ImplicitConstant.newBuilder().setScalarType(ScalarType.INTEGER).setOffset(12));
				break;
			case IMPLICIT_LINEAR:
				builder.setImplicitLinear(
						ImplicitLinear.newBuilder().setScalarType(ScalarType.INTEGER).setStart(1).setIncrement(1));
				break;
			case IMPLICIT_SAW:
				builder.setImplicitSaw(ImplicitSaw.newBuilder().setScalarType(ScalarType.INTEGER).setStart(1)
						.setIncrement(1).setStop(5));
				break;
			case RAW_LINEAR:
				builder.setRawLinear(RawLinear.newBuilder().setScalarType(ScalarType.DOUBLE).setFactor(2).setOffset(10)
						.setValues(DOUBLE_DATA));
				break;
			case RAW_LINEAR_CALIBRATED:
				builder.setRawLinearCalibrated(RawLinearCalibrated.newBuilder().setScalarType(ScalarType.DOUBLE)
						.setOffset(1).setFactor(2).setCalibration(3).setValues(DOUBLE_DATA));
				break;
			case RAW_POLYNOMIAL:
				builder.setRawPolynomial(RawPolynomial.newBuilder().setScalarType(ScalarType.DOUBLE).addCoefficients(1)
						.addCoefficients(2).addCoefficients(3).setValues(DOUBLE_DATA));
				break;
			default:
				break;
			}

			writeRequestList.addValues(builder);
		}

		given().contentType(MIMETYPE_APPLICATION_PROTOBUF).body(writeRequestList.build().toByteArray())
				.post("/values/write").then().log().ifError().assertThat()
				.statusCode(Status.NO_CONTENT.getStatusCode());
	}

	private void writeValuesAllScalarTypes(String channelGroupId, Map<String, ScalarType> channelIds) {
		WriteRequestList.Builder writeRequestList = WriteRequestList.newBuilder();

		for (Entry<String, ScalarType> entry : channelIds.entrySet()) {
			WriteRequest.Builder builder = WriteRequest.newBuilder().setChannelGroupId(channelGroupId)
					.setChannelId(entry.getKey()).setAxisTypeValue(AxisType.XY_AXIS_VALUE).setIndependent(false);
			switch (entry.getValue()) {
			case STRING:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setStringArray(StringArray.newBuilder().addAllValues(SCALARTYPE_STRING)));
				break;
			case DATE:
				builder = builder.setExplicit(
						ExplicitData.newBuilder().setDateArray(DateArray.newBuilder().addAllValues(SCALARTYPE_DATE)));
				break;
			case BOOLEAN:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setBooleanArray(BooleanArray.newBuilder().addAllValues(SCALARTYPE_BOOLEAN)));
				break;
			case BYTE:
				builder = builder.setExplicit(
						ExplicitData.newBuilder().setByteArray(ByteArray.newBuilder().setValues(SCALARTYPE_BYTES)));
				break;
			case SHORT:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setShortArray(ShortArray.newBuilder().addAllValues(SCALARTYPE_SHORTS)));
				break;
			case INTEGER:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setIntegerArray(IntegerArray.newBuilder().addAllValues(SCALARTYPE_INTEGER)));
				break;
			case LONG:
				builder = builder.setExplicit(
						ExplicitData.newBuilder().setLongArray(LongArray.newBuilder().addAllValues(SCALARTYPE_LONG)));
				break;
			case FLOAT:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setFloatArray(FloatArray.newBuilder().addAllValues(SCALARTYPE_FLOAT)));
				break;
			case DOUBLE:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setDoubleArray(DoubleArray.newBuilder().addAllValues(SCALARTYPE_DOUBLE)));
				break;
			case BYTE_STREAM:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setByteStreamArray(ByteStreamArray.newBuilder().addAllValues(SCALARTYPE_BYTE_STREAM)));
				break;
			case FLOAT_COMPLEX:
				builder = builder.setExplicit(ExplicitData.newBuilder()
						.setFloatComplexArray(FloatComplexArray.newBuilder().addAllValues(SCALARTYPE_FLOAT_COMPLEX)));
				break;
			case DOUBLE_COMPLEX:
				builder = builder.setExplicit(ExplicitData.newBuilder().setDoubleComplexArray(
						DoubleComplexArray.newBuilder().addAllValues(SCALARTYPE_DOUBLE_COMPLEX)));
				break;
			default:
				throw new RuntimeException("The ScalarType " + entry.getValue() + " is not supported!");
			}

			writeRequestList.addValues(builder);
		}

		given().contentType(MIMETYPE_APPLICATION_PROTOBUF).body(writeRequestList.build().toByteArray())
				.post("/values/write").then().log().ifError().assertThat()
				.statusCode(Status.NO_CONTENT.getStatusCode());
	}

	private void assertBoolean(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_BOOLEAN".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_BOOLEAN")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_BOOLEAN.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.BOOLEAN)
						.setBooleanArray(BooleanArray.newBuilder().addAllValues(SCALARTYPE_BOOLEAN))
						.addAllFlags(SCALARTYPE_FLAGS).build());

	}

	private void assertByte(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_BYTE".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_BYTE")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
				.setLength(SCALARTYPE_BYTES.size()).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.BYTE)
				.setByteArray(ByteArray.newBuilder().setValues(SCALARTYPE_BYTES)).addAllFlags(SCALARTYPE_FLAGS)
				.build());

	}

	private void assertShort(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_SHORT".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_SHORT")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_SHORTS.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.SHORT)
						.setShortArray(ShortArray.newBuilder().addAllValues(SCALARTYPE_SHORTS))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertInteger(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_INTEGER".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_INTEGER")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_INTEGER.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.INTEGER)
						.setIntegerArray(IntegerArray.newBuilder().addAllValues(SCALARTYPE_INTEGER))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertLong(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_LONG".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_LONG")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
				.setLength(SCALARTYPE_LONG.size()).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.LONG)
				.setLongArray(LongArray.newBuilder().addAllValues(SCALARTYPE_LONG)).addAllFlags(SCALARTYPE_FLAGS)
				.build());
	}

	private void assertFloat(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_FLOAT".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_FLOAT")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_FLOAT.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.FLOAT)
						.setFloatArray(FloatArray.newBuilder().addAllValues(SCALARTYPE_FLOAT))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertDouble(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_DOUBLE".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_DOUBLE")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_DOUBLE.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.DOUBLE)
						.setDoubleArray(DoubleArray.newBuilder().addAllValues(SCALARTYPE_DOUBLE))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertFloatComplex(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_FLOAT_COMPLEX".equals(m.getName())).findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_FLOAT_COMPLEX")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_FLOAT.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.FLOAT_COMPLEX)
						.setFloatComplexArray(FloatComplexArray.newBuilder().addAllValues(SCALARTYPE_FLOAT_COMPLEX))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertDoubleComplex(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_DOUBLE_COMPLEX".equals(m.getName())).findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_DOUBLE_COMPLEX")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_DOUBLE.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.DOUBLE_COMPLEX)
						.setDoubleComplexArray(DoubleComplexArray.newBuilder().addAllValues(SCALARTYPE_DOUBLE_COMPLEX))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertByteStream(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_BYTE_STREAM".equals(m.getName())).findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_BYTE_STREAM")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_DOUBLE.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.BYTE_STREAM)
						.setByteStreamArray(ByteStreamArray.newBuilder().addAllValues(SCALARTYPE_BYTE_STREAM))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertString(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_STRING".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_STRING")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(SCALARTYPE_STRING.size()).setAxisType(Mdm.AxisType.XY_AXIS)
						.setScalarType(Mdm.ScalarType.STRING)
						.setStringArray(StringArray.newBuilder().addAllValues(SCALARTYPE_STRING))
						.addAllFlags(SCALARTYPE_FLAGS).build());
	}

	private void assertDate(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_DATE".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_DATE")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
				.setLength(SCALARTYPE_DATE.size()).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.DATE)
				.setDateArray(DateArray.newBuilder().addAllValues(SCALARTYPE_DATE)).addAllFlags(SCALARTYPE_FLAGS)
				.build());
	}

	private void assertExplicit(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_EXPLICIT".equals(m.getName()))
				.findFirst();

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_EXPLICIT")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(LENGTH).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.INTEGER)
						.setIntegerArray(IntegerArray.newBuilder().addAllValues(INTS)).addAllFlags(FLAGS).build());

	}

	private void assertImplicitConstant(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_IMPLICIT_CONSTANT".equals(m.getName())).findFirst();

		List<Integer> constantValues = IntStream.range(0, LENGTH).map(i -> 12).boxed().collect(Collectors.toList());

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_IMPLICIT_CONSTANT")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME)).setLength(LENGTH)
				.setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.INTEGER)
				.setIntegerArray(IntegerArray.newBuilder().addAllValues(constantValues)).addAllFlags(FLAGS).build());

	}

	private void assertImplicitLinear(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_IMPLICIT_LINEAR".equals(m.getName())).findFirst();

		List<Integer> linearValues = IntStream.range(0, LENGTH).map(i -> i + 1).boxed().collect(Collectors.toList());

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_IMPLICIT_LINEAR")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME)).setLength(LENGTH)
				.setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.INTEGER)
				.setIntegerArray(IntegerArray.newBuilder().addAllValues(linearValues)).addAllFlags(FLAGS).build());

	}

	private void assertImplicitSaw(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_IMPLICIT_SAW".equals(m.getName())).findFirst();

		List<Integer> sawValues = IntStream.range(0, LENGTH).map(i -> i % 4 + 1).boxed().collect(Collectors.toList());

		softly.assertThat(mv)
				.contains(Mdm.MeasuredValues.newBuilder().setName("Channel_IMPLICIT_SAW")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(LENGTH).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.INTEGER)
						.setIntegerArray(IntegerArray.newBuilder().addAllValues(sawValues)).addAllFlags(FLAGS).build());

	}

	private void assertRawLinear(SoftAssertions softly, MeasuredValuesList mvl) throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream().filter(m -> "Channel_RAW_LINEAR".equals(m.getName()))
				.findFirst();

		List<Double> rawLinearValues = DOUBLES.stream().mapToDouble(d -> 2 * d + 10).boxed()
				.collect(Collectors.toList());

		softly.assertThat(mv).contains(Mdm.MeasuredValues.newBuilder().setName("Channel_RAW_LINEAR")
				.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME)).setLength(LENGTH)
				.setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.DOUBLE)
				.setDoubleArray(DoubleArray.newBuilder().addAllValues(rawLinearValues)).addAllFlags(FLAGS).build());
	}

	private void assertRawLinearCalibrated(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_RAW_LINEAR_CALIBRATED".equals(m.getName())).findFirst();

		List<Double> rawLinCalValues = DOUBLES.stream().mapToDouble(d -> (1 + 2 * d) * 3).boxed()
				.collect(Collectors.toList());

		softly.assertThat(mv.get())
				.isEqualToIgnoringGivenFields(Mdm.MeasuredValues.newBuilder().setName("Channel_RAW_LINEAR_CALIBRATED")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(LENGTH).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.DOUBLE)
						.setDoubleArray(DoubleArray.newBuilder().addAllValues(rawLinCalValues)).addAllFlags(FLAGS)
						.build(), "values", "values_", "memoizedIsInitialized");

		softly.assertThat(mv.get().getDoubleArray().getValuesList()).usingElementComparator(DOUBLE_COMP)
				.isEqualTo(rawLinCalValues);
	}

	private void assertRawPolynomial(SoftAssertions softly, MeasuredValuesList mvl)
			throws InvalidProtocolBufferException {

		Optional<MeasuredValues> mv = mvl.getValuesList().stream()
				.filter(m -> "Channel_RAW_POLYNOMIAL".equals(m.getName())).findFirst();

		List<Double> rawPolynomialValues = DOUBLES.stream().mapToDouble(d -> 1 + 2 * d + 3 * d * d).boxed()
				.collect(Collectors.toList());

		softly.assertThat(mv.get())
				.isEqualToIgnoringGivenFields(Mdm.MeasuredValues.newBuilder().setName("Channel_RAW_POLYNOMIAL")
						.setUnit(getTestDataValue(UnitResourceIntegrationTest.class, TESTDATA_ENTITY_NAME))
						.setLength(LENGTH).setAxisType(Mdm.AxisType.XY_AXIS).setScalarType(Mdm.ScalarType.DOUBLE)
						.setDoubleArray(DoubleArray.newBuilder().addAllValues(rawPolynomialValues)).addAllFlags(FLAGS)
						.build(), "values", "values_", "memoizedIsInitialized");

		softly.assertThat(mv.get().getDoubleArray().getValuesList()).usingElementComparator(DOUBLE_COMP)
				.isEqualTo(rawPolynomialValues);
	}

	private static Map<String, DataCase> createChannelsForDataCase() {
		// Create channels
		Map<String, DataCase> channelIds = new HashMap<>();
		for (DataCase dataCase : WriteRequest.DataCase.values()) {
			if (dataCase == DataCase.DATA_NOT_SET) {
				continue;
			}
			JsonObject json = new JsonObject();
			json.add(ResourceConstants.ENTITYATTRIBUTE_NAME, new JsonPrimitive("Channel_" + dataCase.name()));
			json.add("Measurement",
					new JsonPrimitive(getTestDataValue(MeasurementResourceIntegrationTest.class, TESTDATA_ENTITY_ID)));
			json.add("Quantity",
					new JsonPrimitive(getTestDataValue(QuantityResourceIntegrationTest.class, TESTDATA_ENTITY_ID)));

			ExtractableResponse<io.restassured.response.Response> response = given().contentType(ContentType.JSON)
					.body(json.toString()).post("/channels").then().log().ifError().contentType(ContentType.JSON)
					.extract();

			LOGGER.debug("Channel created " + response.asString());
			channelIds.put(response.path("data.first().id"), dataCase);
		}
		return channelIds;
	}

	private static Map<String, ScalarType> createChannelsForScalarTypes() {
		Map<String, ScalarType> channelIds = new HashMap<>();
		for (ScalarType scalarType : scalarTypes) {
			JsonObject json = new JsonObject();
			json.add(ResourceConstants.ENTITYATTRIBUTE_NAME, new JsonPrimitive("Channel_" + scalarType.name()));
			json.add("Measurement",
					new JsonPrimitive(getTestDataValue(MeasurementResourceIntegrationTest.class, TESTDATA_ENTITY_ID)));
			json.add("Quantity",
					new JsonPrimitive(getTestDataValue(QuantityResourceIntegrationTest.class, TESTDATA_ENTITY_ID)));

			ExtractableResponse<io.restassured.response.Response> response = given().contentType(ContentType.JSON)
					.body(json.toString()).post("/channels").then().log().ifError().contentType(ContentType.JSON)
					.extract();

			LOGGER.debug("Channel created " + response.asString());
			channelIds.put(response.path("data.first().id"), scalarType);
		}
		return channelIds;
	}

	private static String createChannelGroup() {
		// Create channelGroup
		JsonObject json = new JsonObject();
		json.add(ResourceConstants.ENTITYATTRIBUTE_NAME, new JsonPrimitive("ChannelGroup1"));
		json.add(TESTDATA_NUMBER_OF_VALUES, new JsonPrimitive(LENGTH));
		json.add("Measurement",
				new JsonPrimitive(getTestDataValue(MeasurementResourceIntegrationTest.class, TESTDATA_ENTITY_ID)));

		ExtractableResponse<io.restassured.response.Response> response = given().contentType(ContentType.JSON)
				.body(json.toString()).post("/channelgroups").then().log().ifError().contentType(ContentType.JSON)
				// do not check for name equality as that might be created randomly
				.and().body("data.first().type", equalTo("ChannelGroup")).extract();

		LOGGER.debug("ChannelGroup created " + response.asString());

		return response.path("data.first().id");
	}

	private static Comparator<Double> DOUBLE_COMP = new Comparator<Double>() {

		private double precision = 1E-6;

		@Override
		public int compare(Double o1, Double o2) {
			double diff = Math.abs(o1.doubleValue() - o2.doubleValue());
			if (diff <= precision)
				return 0;
			return diff < 0.0 ? -1 : 1;
		}

	};

	@AfterClass
	public static void tearDownAfterClass() {
		// call tearDownAfterClass() of parent entity
		QuantityResourceIntegrationTest.tearDownAfterClass();
		MeasurementResourceIntegrationTest.tearDownAfterClass();
	}
}
