/*=============================================================================#
 # Copyright (c) 2020, 2021 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.rj.data.impl;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import static org.eclipse.statet.rj.data.impl.AbstractRStore.DEFAULT_LONG_DATA_SEGMENT_LENGTH;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.rj.data.RIntegerStore;
import org.eclipse.statet.rj.data.RNumericStore;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RStore;


@NonNullByDefault
public abstract class RNumericStoreTest extends AbstractRStoreTest {
	
	
	static class NumCaseData extends CaseData<RNumericStore> {
		
		final static Function<NumCaseData, RNumericStore> REF_CONSTRUCTOR= new RNumericB32StoreTest()::createStore;
		
		final double[] values;
		
		
		public NumCaseData(final String label, final double[] values, final boolean[] nas) {
			super(label, nas);
			assert (values.length == this.length);
			assert (nas.length == this.length);
			this.values= values;
			
			setReference(REF_CONSTRUCTOR.apply(this));
		}
		
		public NumCaseData(final String label, final double[] values) {
			super(label, values.length);
			assert (values.length == this.length);
			this.values= values;
			
			setReference(REF_CONSTRUCTOR.apply(this));
		}
		
	}
	
	protected static final List<NumCaseData> DEFAULT_DATA_SOURCES;
	static {
		final var datas= new ArrayList<NumCaseData>();
		
		datas.add(new NumCaseData("empty", new double[0]));
		
		datas.add(new NumCaseData("single-0", new double[] { 0 }));
		datas.add(new NumCaseData("single-1", new double[] { 1 }));
		datas.add(new NumCaseData("single-Min", new double[] { Double.MIN_VALUE }));
		datas.add(new NumCaseData("single-Max", new double[] { Double.MAX_VALUE }));
		datas.add(new NumCaseData("single-NA", new double[] { 0 }, new boolean[] { true }));
		
		{	final double[] values= new double[0x1FF];
			for (int i= 0; i < values.length; i++) {
				values[i]= i - 0xFF;
			}
			datas.add(new NumCaseData("seq", values));
		}
		{	final double[] values= new double[0xFF];
			final boolean[] nas= new boolean[values.length];
			int i= 0;
			values[i++]= 0;
			values[i++]= -0;
			values[i++]= +1;
			values[i++]= -1;
			values[i++]= Double.MIN_NORMAL;
			values[i++]= Double.MIN_VALUE;
			values[i++]= Double.MAX_VALUE;
			values[i++]= Double.POSITIVE_INFINITY;
			values[i++]= -Double.NEGATIVE_INFINITY;
			values[i++]= Double.NaN;
			nas[i++]= true;
			datas.add(new NumCaseData("special", values, nas));
		}
		
		{	final Random rand= new Random(16857);
			final double[] values= new double[100000];
			for (int i= 0; i < values.length; i++) {
				values[i]= rand.nextDouble();
			}
			datas.add(new NumCaseData("rand100000", values));
		}
		if (isBigDataEnabled(8)) {
			final Random rand= new Random(46);
			final double[] values= new double[DEFAULT_LONG_DATA_SEGMENT_LENGTH * 2 + 13];
			for (int i= 0; i < values.length; i++) {
				values[i]= rand.nextDouble();
			}
			datas.add(new NumCaseData("randMultiSeg", values));
		}
		
		DEFAULT_DATA_SOURCES= datas;
	}
	
	
	public RNumericStoreTest() {
	}
	
	
	public static List<NumCaseData> provideCaseDatas() {
		return new ArrayList<>(DEFAULT_DATA_SOURCES);
	}
	
	protected abstract RNumericStore createStore(final NumCaseData data);
	
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getStoreType(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		assertEquals(RStore.NUMERIC, store.getStoreType());
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getBaseVectorRClassName(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		assertEquals(RObject.CLASSNAME_NUMERIC, store.getBaseVectorRClassName());
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void length(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		checkLength(data, store);
	}
	
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void isNA(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		checkIsNA(data, store);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void isMissing(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]
					|| Double.isNaN(data.values[i0])) {
				assertTrue(store.isMissing(i0), storeDiffersAt(i0));
				assertTrue(store.isMissing((long)i0), storeDiffersAt(i0));
			}
			else {
				assertFalse(store.isMissing(i0), storeDiffersAt(i0));
				assertFalse(store.isMissing((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::isMissing, store::isMissing);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void isNaN(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				assertFalse(store.isNaN(i0), storeDiffersAt(i0));
				assertFalse(store.isNaN((long)i0), storeDiffersAt(i0));
			}
			else if (Double.isNaN(data.values[i0])) {
				assertTrue(store.isNaN(i0), storeDiffersAt(i0));
				assertTrue(store.isNaN((long)i0), storeDiffersAt(i0));
			}
			else {
				assertFalse(store.isNaN(i0), storeDiffersAt(i0));
				assertFalse(store.isNaN((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::isNaN, store::isNaN);
	}
	
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	@SuppressWarnings("boxing")
	public void getLogi(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			try {
				if (data.nas[i0]) {
					// undefined
				}
				else {
					final Boolean expected= Boolean.valueOf(data.values[i0] != 0);
					assertEquals(expected, store.getLogi(i0), storeDiffersAt(i0));
					assertEquals(expected, store.getLogi((long)i0), storeDiffersAt(i0));
				}
			}
			catch (final NumberFormatException e) {
				fail(storeDiffersAt(i0).get(), e);
			}
		}
		assertIndexOutOfBounds(data, store::getLogi, store::getLogi);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getInt(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			try {
				if (data.nas[i0]) {
					// undefined
				}
				else if (data.values[i0] >= RIntegerStore.MIN_INT && data.values[i0] <= RIntegerStore.MAX_INT) {
					final int expected= (int)data.values[i0];
					assertEquals(expected, store.getInt(i0), storeDiffersAt(i0));
					assertEquals(expected, store.getInt((long)i0), storeDiffersAt(i0));
				}
				else {
					// ?
				}
			}
			catch (final NumberFormatException e) {
				fail(storeDiffersAt(i0).get(), e);
			}
		}
		assertIndexOutOfBounds(data, store::getInt, store::getInt);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getNum(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				// undefined
			}
			else {
				final double expected= data.values[i0];
				assertEquals(expected, store.getNum(i0), storeDiffersAt(i0));
				assertEquals(expected, store.getNum((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::getNum, store::getNum);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getCplx(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				// undefined
			}
			else {
				final double expectedRe= data.values[i0];
				assertEquals(expectedRe, store.getCplxRe(i0), storeDiffersAt(i0));
				assertEquals(expectedRe, store.getCplxRe((long)i0), storeDiffersAt(i0));
				assertEquals(0, store.getCplxIm(i0), storeDiffersAt(i0));
				assertEquals(0, store.getCplxIm((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::getNum, store::getNum);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getChar(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				// undefined
			}
			else {
				final String expected= Double.toString(data.values[i0]).replace("Infinity", "Inf");
				assertEquals(expected, store.getChar(i0), storeDiffersAt(i0));
				assertEquals(expected, store.getChar((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::getChar, store::getChar);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void getRaw(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		assertUnsupported(data, store::getRaw, store::getRaw);
	}
	
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void get(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				assertNull(store.get(i0), storeDiffersAt(i0));
			}
			else {
				final Double expected= Double.valueOf(data.values[i0]);
				assertEquals(expected, store.get(i0), storeDiffersAt(i0));
				assertEquals(expected, store.get((long)i0), storeDiffersAt(i0));
			}
		}
		assertIndexOutOfBounds(data, store::get, store::get);
	}
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void toArray(final NumCaseData data) {
		final RNumericStore store= createStore(data);
		
		final @Nullable Double[] array= store.toArray();
		
		assertEquals(data.values.length, array.length);
		
		for (int i= 0; i < data.length; i++) {
			final int i0= i;
			if (data.nas[i0]) {
				assertNull(array[i0], arrayDiffersAt(i0));
			}
			else {
				final Double expected= Double.valueOf(data.values[i0]);
				assertEquals(expected, array[i0], arrayDiffersAt(i0));
			}
		}
	}
	
	
	@ParameterizedTest
	@MethodSource("provideCaseDatas")
	public void writeExternal(final NumCaseData data) throws IOException {
		final RNumericStore store= createStore(data);
		
		if (store instanceof ExternalizableRStore) {
			final byte[] ser= writeExternal(store);
			assertArrayEquals(data.getExternalBytes(), ser);
		}
	}
	
}
