/********************************************************************************
 * 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.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();
	}
}
