package geniusweb.issuevalue;

import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Nonnull;

import org.junit.Test;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import tudelft.utilities.junit.GeneralTests;

public class NumberValueTest extends GeneralTests<NumberValue> {
	private final @Nonnull NumberValue value = new NumberValue("12.31");
	private final @Nonnull NumberValue value1 = new NumberValue("12.31");
	private final @Nonnull NumberValue valueb = new NumberValue(
			"12.3100000000001");
	private final @Nonnull NumberValue valuec = new NumberValue("1000");
	private final @Nonnull NumberValue valuec2 = new NumberValue("1e+3");
	private final @Nonnull String serialized = "12.31";

	private final @Nonnull String bigserialized = "8748703924870439218876954320948372058";
	private final @Nonnull NumberValue bigvalue = new NumberValue(
			bigserialized);
	private static final ObjectMapper jackson = new ObjectMapper();

	@Override
	public List<List<NumberValue>> getGeneralTestData() {
		return Arrays.asList(Arrays.asList(value, value1),
				Arrays.asList(valueb), Arrays.asList(valuec, valuec2));
	}

	@Override
	public List<String> getGeneralTestStrings() {
		// 1000 and 1e+3 are bot ok
		return Arrays.asList("12.31", "12.3100000000001", "1...");
	}

	@Test
	public void testSerialize() throws JsonProcessingException {
		assertEquals(serialized, jackson.writeValueAsString(value));
	}

	@Test
	public void testDeserialize() throws IOException {
		assertEquals(value, jackson.readValue(serialized, NumberValue.class));

	}

	@Test
	public void testDeserializeFromValue() throws IOException {
		assertEquals(value, jackson.readValue(serialized, Value.class));

	}

	@Test
	public void testBigSerialize() throws JsonProcessingException {
		assertEquals(bigserialized, jackson.writeValueAsString(bigvalue));
	}

	@Test
	public void testBigDeserialize() throws IOException {
		assertEquals(bigvalue,
				jackson.readValue(bigserialized, NumberValue.class));

	}

	@Test
	public void testSerializeShorts() throws IOException {
		//System.out.println(
		//		jackson.writeValueAsString(new short[] { 1, 2, 3, 4, 5 }));

	}

	@Test
	public void testDeserializeShorts() throws IOException {
		@SuppressWarnings("unchecked")
		ArrayList<Integer> list = jackson.readValue("[1,2,3,4,5]",
				ArrayList.class);
		//System.out.println(list);
		//System.out.println(list.get(0).getClass());

	}

	@Test
	public void testDeserializeMix() throws IOException {
		@SuppressWarnings("unchecked")
		ArrayList<Object> list = jackson.readValue("[\"short\",1,2,3,4,5]",
				ArrayList.class);
		//System.out.println(list);
		//System.out.println(list.get(0).getClass());

	}

	/**
	 * Showing that we CAN deserialize big numbers without double quotes
	 * correctly, if we tell jackson upfront that it's a BigDecimal.
	 */
	@Test
	public void testDeserializePlainNumber()
			throws JsonParseException, JsonMappingException, IOException {
		@Nonnull
		String valstr = "483958743698732691487326987569213874694328974329874328947320984372498327493827432987231874681273648127";
		@Nonnull
		BigDecimal val = jackson.readValue(valstr, BigDecimal.class);
		assertEquals(valstr, val.toString());
	}

	@Test
	public void testNumberBlab() throws IOException {
		// jackson.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
		assertEquals(value, jackson.readValue("12.31", Value.class));

	}

	@Test
	public void testDeserializeScientificNotation()
			throws JsonParseException, JsonMappingException, IOException {
		@Nonnull
		String valstr = "9E+2";
		@Nonnull
		Value val = jackson.readValue(valstr, Value.class);
		assertEquals(valstr, val.toString());
		assertEquals(val, new NumberValue(new BigDecimal("900")));
	}

}