// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.a.rttests;

import static org.apache.juneau.internal.DateUtils.*;
import static org.apache.juneau.testutils.TestUtils.*;
import static org.junit.Assert.*;

import java.io.*;
import java.util.*;

import javax.xml.datatype.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.testutils.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.transforms.*;
import org.apache.juneau.utils.*;
import org.junit.*;

/**
 * Tests designed to serialize and parse objects to make sure we end up
 * with the same objects for all serializers and parsers.
 */
@SuppressWarnings({"unchecked","rawtypes","serial"})
public class RoundTripTransformBeansTest extends RoundTripTest {

	public RoundTripTransformBeansTest(String label, SerializerBuilder s, ParserBuilder p, int flags) throws Exception {
		super(label, s == null ? null : s.applyAnnotations(Bc.class, E1c.class, F1c.class, F2ac.class), p == null ? null : p.applyAnnotations(Bc.class, E1c.class, F1c.class, F2ac.class), flags);

	}

	//====================================================================================================
	// testSwapBeans1
	//====================================================================================================
	@Test
	public void testSwapBeans1() throws Exception {
		Class<?>[] f = {
			ByteArraySwap.Base64.class
		};
		pojoSwaps(f);
		A t = new A().init();
		t = roundTrip(t, A.class);

		// ByteArrayBase64Swap
		assertEquals(3, t.fByte[3]);
		assertNull(t.fnByte);
		assertEquals(5, t.faByte[2][1]);
		assertEquals(6, t.flByte.get(1)[2]);
		assertNull(t.flByte.get(2));
		assertEquals(6, t.fmByte.get("bar")[2]);
		assertNull(t.fmByte.get("baz"));

		// CalendarSwap
		t.fCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));
		assertEquals(2001, t.fCalendar.get(Calendar.YEAR));
		assertEquals(01, t.fCalendar.get(Calendar.MONTH));
		assertEquals(02, t.fCalendar.get(Calendar.DATE));
		assertEquals(03, t.fCalendar.get(Calendar.HOUR));
		assertEquals(04, t.fCalendar.get(Calendar.MINUTE));
		assertEquals(05, t.fCalendar.get(Calendar.SECOND));

		t.faCalendar[0].setTimeZone(TimeZone.getTimeZone("GMT"));
		assertEquals(2001, t.faCalendar[0].get(Calendar.YEAR));
		assertEquals(01, t.faCalendar[0].get(Calendar.MONTH));
		assertEquals(02, t.faCalendar[0].get(Calendar.DATE));
		assertEquals(03, t.faCalendar[0].get(Calendar.HOUR));
		assertEquals(04, t.faCalendar[0].get(Calendar.MINUTE));
		assertEquals(05, t.faCalendar[0].get(Calendar.SECOND));
		assertNull(t.fnCalendar);
		assertNull(t.fn2Calendar);

		// DateSwap
		assertEquals(1000, t.fDate.getTime());
		assertNull(t.fnDate);
		assertEquals(3000, t.faDate[2].getTime());
		assertEquals(4000, t.flDate.get(0).getTime());
		assertNull(t.flDate.get(1));
		assertEquals(5000, t.fmDate.get("foo").getTime());
		assertNull(t.fmDate.get("bar"));
	}

	public static class A {

		// Test ByteArrayBase64Swap
		public byte[] fByte;
		public byte[] fnByte;
		public byte[][] faByte;
		public List<byte[]> flByte;
		public Map<String,byte[]> fmByte;

		public GregorianCalendar fCalendar;
		public GregorianCalendar fnCalendar;
		public Calendar fn2Calendar;
		public GregorianCalendar[] faCalendar;

		public Date fDate;
		public Date fnDate;
		public Date[] faDate;
		public List<Date> flDate;
		public Map<String,Date> fmDate;

		public A init() {
			fByte = new byte[]{0,1,2,3};
			fnByte = null;
			faByte = new byte[][]{{0,1},{2,3},{4,5}};
			flByte = new AList<byte[]>()
				.append(new byte[]{1,2,3})
				.append(new byte[]{4,5,6})
				.append(null)
			;
			fmByte = new AMap<String,byte[]>()
				.append("foo", new byte[]{1,2,3})
				.append("bar", new byte[]{4,5,6})
				.append("baz", null)
			;

			fCalendar = new GregorianCalendar() {{
				set(2001, 01, 02, 03, 04, 05);
				setTimeZone(TimeZone.getTimeZone("GMT"));
			}};
			fnCalendar = null;
			fn2Calendar = null;
			faCalendar = new GregorianCalendar[]{
				new GregorianCalendar() {{
					set(2001, 01, 02, 03, 04, 05);
					setTimeZone(TimeZone.getTimeZone("GMT"));
				}}
			};

			fDate = new Date(1000);
			fnDate = null;
			faDate = new Date[]{
				new Date(1000), new Date(2000), new Date(3000)
			};
			flDate = new AList<Date>()
				.append(new Date(4000))
				.append(null)
			;
			fmDate = new AMap<String,Date>()
				.append("foo", new Date(5000))
				.append("bar", null)
			;
			return this;
		}
	}


	//====================================================================================================
	// testSwapBeans2
	//====================================================================================================
	@Test
	public void testSwapBeans2() throws Exception {
		Class<?>[] f = {
			ByteArraySwap.Base64.class
		};
		pojoSwaps(f);
		A t = new A().init();
		t = roundTrip(t, A.class);

		// ByteArrayBase64Swap
		assertEquals(3, t.fByte[3]);
		assertNull(t.fnByte);
		assertEquals(5, t.faByte[2][1]);
		assertEquals(6, t.flByte.get(1)[2]);
		assertNull(t.flByte.get(2));
		assertEquals(6, t.fmByte.get("bar")[2]);
		assertNull(t.fmByte.get("baz"));

		// CalendarSwap
		t.fCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));
		assertEquals(2001, t.fCalendar.get(Calendar.YEAR));
		assertEquals(01, t.fCalendar.get(Calendar.MONTH));
		// Note: We lose precision on the following because of the transform type.
		//assertEquals(02, b.fCalendar.get(Calendar.DATE));
		//assertEquals(03, b.fCalendar.get(Calendar.HOUR));
		//assertEquals(04, b.fCalendar.get(Calendar.MINUTE));
		//assertEquals(05, b.fCalendar.get(Calendar.SECOND));

		t.faCalendar[0].setTimeZone(TimeZone.getTimeZone("GMT"));
		assertEquals(2001, t.faCalendar[0].get(Calendar.YEAR));
		assertEquals(01, t.faCalendar[0].get(Calendar.MONTH));
		// Note: We lose precision on the following because of the transform type.
		//assertEquals(02, b.faCalendar[0].get(Calendar.DATE));
		//assertEquals(03, b.faCalendar[0].get(Calendar.HOUR));
		//assertEquals(04, b.faCalendar[0].get(Calendar.MINUTE));
		//assertEquals(05, b.faCalendar[0].get(Calendar.SECOND));
		assertNull(t.fnCalendar);
		assertNull(t.fn2Calendar);

		// DateSwap
		assertEquals(1000, t.fDate.getTime() % 3600000);
		assertNull(t.fnDate);
		assertEquals(3000, t.faDate[2].getTime() % 3600000);
		assertEquals(4000, t.flDate.get(0).getTime() % 3600000);
		assertNull(t.flDate.get(1));
		assertEquals(5000, t.fmDate.get("foo").getTime() % 3600000);
		assertNull(t.fmDate.get("bar"));
	}

	//====================================================================================================
	// testSwaps - Bean.pojoSwaps annotation
	//====================================================================================================
	@Test
	public void testSwaps() throws Exception {
		B t = new B();
		t.f1 = "bar";
		t = roundTrip(t, B.class);

		assertEquals("bar", t.f1);
	}

	@Swap(BSwap.class)
	public static class B {
		public String f1;
	}

	public static class BSwap extends StringSwap<B> {
		@Override /* PojoSwap */
		public String swap(BeanSession session, B o) throws SerializeException {
			return o.f1;
		}
		@Override /* PojoSwap */
		public B unswap(BeanSession session, String f, ClassMeta<?> hint) throws ParseException {
			B b1 = new B();
			b1.f1 = f;
			return b1;
		}
	}

	@Test
	public void testSwaps_usingConfig() throws Exception {
		Bc t = new Bc();
		t.f1 = "bar";
		t = roundTrip(t, Bc.class);

		assertEquals("bar", t.f1);
	}

	@BeanConfig(applySwap=@Swap(on="Bc",value=BcSwap.class))
	public static class Bc {
		public String f1;
	}

	public static class BcSwap extends StringSwap<Bc> {
		@Override /* PojoSwap */
		public String swap(BeanSession session, Bc o) throws SerializeException {
			return o.f1;
		}
		@Override /* PojoSwap */
		public Bc unswap(BeanSession session, String f, ClassMeta<?> hint) throws ParseException {
			Bc b1 = new Bc();
			b1.f1 = f;
			return b1;
		}
	}

	//====================================================================================================
	// testXMLGregorianCalendar - Test XMLGregorianCalendarSwap class.
	//====================================================================================================
	@Test
	public void testXMLGregorianCalendar() throws Exception {

		if (isValidationOnly())
			return;

		GregorianCalendar gc = new GregorianCalendar();
		XMLGregorianCalendar c = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);

		Serializer s = getSerializer();
		Parser p = getParser();

		Object r = s.serialize(c);
		XMLGregorianCalendar c2 = p.parse(r, XMLGregorianCalendar.class);
		assertEquals(c, c2);
	}

	//====================================================================================================
	// testSubTypeWithGenerics
	//====================================================================================================
	@Test
	public void testSubTypeWithGenerics() throws Exception {
		JsonSerializer s = JsonSerializer.DEFAULT.builder().addBeanTypes().addRootType().build();

		C1 c1 = C3.create();
		String r = s.serialize(c1);
		assertEquals("{\"_type\":\"C3\",\"f1\":{\"f2\":\"f2\",\"f3\":3}}", r);
	}


	@Bean(dictionary={C3.class})
	public static interface C1<T> extends Serializable {
		void setF1(T f1);
		T getF1();
	}

	public abstract static class C2<T> implements C1<T> {
		protected T f1;

		@Override /* C1 */
		public void setF1(T f1) {
			this.f1 = f1;
		}

		@Override /* C1 */
		public T getF1() {
			return f1;
		}
	}

	@Bean(typeName="C3")
	public static class C3<T> extends C2<T> {

		public static C3 create() {
			C3 c3 = new C3<>();
			CDTO cdto = new CDTO();
			cdto.f2 = "f2";
			cdto.f3 = 3;
			c3.f1 = cdto;
			return c3;
		}

		@Override /* C1 */
		public void setF1(T f1) {
			this.f1 = f1;
		}

		@Override /* C1 */
		public T getF1() {
			return f1;
		}
	}

	public static class CDTO {
		public String f2;
		public int f3;
	}

	//====================================================================================================
	// Surrogate transforms
	//====================================================================================================
	@Test
	public void testSurrogates() throws Exception {
		pojoSwaps(D2.class);

		JsonSerializer s = JsonSerializer.create().ssq().pojoSwaps(D2.class).build();
		JsonParser p = JsonParser.create().pojoSwaps(D2.class).build();
		Object r;
		D1 x = D1.create();

		r = s.serialize(x);
		assertEquals("{f2:'f1'}", r);

		x = p.parse(r, D1.class);
		assertEquals("f1", x.f1);

		r = getSerializer().serialize(x);
		assertTrue(TestUtils.toString(r).contains("f2"));

		x = roundTrip(x, D1.class);
	}

	public static class D1 {
		public String f1;

		public static D1 create() {
			D1 x = new D1();
			x.f1 = "f1";
			return x;
		}
	}

	public static class D2 implements Surrogate {
		public String f2;
		public D2(D1 x) {
			f2 = x.f1;
		}
		public D2() {}
		public D1 create() {
			D1 x = new D1();
			x.f1 = this.f2;
			return x;
		}
	}

	@Test
	public void testSurrogatesThroughAnnotation() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT;
		JsonParser p = JsonParser.DEFAULT;
		Object r;
		E1 x = E1.create();

		r = s.serialize(x);
		assertEquals("{f2:'f1'}", r);

		x = p.parse(r, E1.class);
		assertEquals("f1", x.f1);

		r = getSerializer().serialize(x);
		assertTrue(TestUtils.toString(r).contains("f2"));

		x = roundTrip(x, E1.class);
	}

	@Swap(E2.class)
	public static class E1 {
		public String f1;

		public static E1 create() {
			E1 x = new E1();
			x.f1 = "f1";
			return x;
		}
	}

	public static class E2 implements Surrogate {
		public String f2;
		public E2(E1 x) {
			f2 = x.f1;
		}
		public E2() {}
		public E1 create() {
			E1 x = new E1();
			x.f1 = this.f2;
			return x;
		}
	}

	@Test
	public void testSurrogatesThroughAnnotation_usingConfig() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(E1c.class).build();
		JsonParser p = JsonParser.DEFAULT.builder().applyAnnotations(E1c.class).build();
		Object r;
		E1c x = E1c.create();

		r = s.serialize(x);
		assertEquals("{f2:'f1'}", r);

		x = p.parse(r, E1c.class);
		assertEquals("f1", x.f1);

		r = getSerializer().serialize(x);
		assertTrue(TestUtils.toString(r).contains("f2"));

		x = roundTrip(x, E1c.class);
	}

	@BeanConfig(applySwap=@Swap(on="E1c",value=E2c.class))
	public static class E1c {
		public String f1;

		public static E1c create() {
			E1c x = new E1c();
			x.f1 = "f1";
			return x;
		}
	}

	public static class E2c implements Surrogate {
		public String f2;
		public E2c(E1c x) {
			f2 = x.f1;
		}
		public E2c() {}
		public E1c create() {
			E1c x = new E1c();
			x.f1 = this.f2;
			return x;
		}
	}

	//====================================================================================================
	// Transforms on private fields.
	//====================================================================================================

	public static class F1 {

		@Swap(TemporalCalendarSwap.IsoLocalDateTime.class)
		private Calendar c;

		public void setC(Calendar c) {
			this.c = c;
		}

		public Calendar getC() {
			return c;
		}

		public static F1 create() {
			F1 x = new F1();
			x.setC(parseISO8601Calendar("2018-12-12T05:12:00"));
			return x;
		}
	}

	@Test
	public void testSwapOnPrivateField() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT;
		JsonParser p = JsonParser.DEFAULT;

		F1 x = F1.create();
		String r = null;

		r = s.serialize(x);
		assertEquals("{c:'2018-12-12T05:12:00'}", r);

		x = p.parse(r, F1.class);
		assertObjectEquals("{c:'2018-12-12T05:12:00'}", x);

		x = roundTrip(x, F1.class);
	}

	@BeanConfig(applySwap=@Swap(on="F1c.c", value=TemporalCalendarSwap.IsoLocalDateTime.class))
	public static class F1c {

		private Calendar c;

		public void setC(Calendar c) {
			this.c = c;
		}

		public Calendar getC() {
			return c;
		}

		public static F1c create() {
			F1c x = new F1c();
			x.setC(parseISO8601Calendar("2018-12-12T05:12:00"));
			return x;
		}
	}

	@Test
	public void testSwapOnPrivateField_usingConfig() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(F1c.class).build();
		JsonParser p = JsonParser.DEFAULT.builder().applyAnnotations(F1c.class).build();

		F1c x = F1c.create();
		String r = null;

		r = s.serialize(x);
		assertEquals("{c:'2018-12-12T05:12:00'}", r);

		x = p.parse(r, F1c.class);
		assertObjectEquals("{c:'2018-12-12T05:12:00'}", x, s);

		x = roundTrip(x, F1c.class);
	}

	public static class F2a {

		@Swap(TemporalCalendarSwap.IsoLocalDateTime.class)
		protected Calendar c;

	}

	public static class F2 extends F2a {

		public void setC(Calendar c) {
			this.c = c;
		}

		public Calendar getC() {
			return c;
		}

		public static F2 create() {
			F2 x = new F2();
			x.setC(parseISO8601Calendar("2018-12-12T05:12:00"));
			return x;
		}
	}

	@Test
	public void testSwapOnPrivateField_Inherited() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT;
		JsonParser p = JsonParser.DEFAULT;

		F2 x = F2.create();
		String r = null;

		r = s.serialize(x);
		assertEquals("{c:'2018-12-12T05:12:00'}", r);

		x = p.parse(r, F2.class);
		assertObjectEquals("{c:'2018-12-12T05:12:00'}", x);

		x = roundTrip(x, F2.class);
	}

	@BeanConfig(applySwap=@Swap(on="F2ac.c", value=TemporalCalendarSwap.IsoLocalDateTime.class))
	public static class F2ac {
		protected Calendar c;
	}

	public static class F2c extends F2ac {

		public void setC(Calendar c) {
			this.c = c;
		}

		public Calendar getC() {
			return c;
		}

		public static F2c create() {
			F2c x = new F2c();
			x.setC(parseISO8601Calendar("2018-12-12T05:12:00"));
			return x;
		}
	}

	@Test
	public void testSwapOnPrivateField_Inherited_usingConfig() throws Exception {
		JsonSerializer s = SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(F2ac.class).build();
		JsonParser p = JsonParser.DEFAULT.builder().applyAnnotations(F2ac.class).build();

		F2 x = F2.create();
		String r = null;

		r = s.serialize(x);
		assertEquals("{c:'2018-12-12T05:12:00'}", r);

		x = p.parse(r, F2.class);
		assertObjectEquals("{c:'2018-12-12T05:12:00'}", x, s);

		x = roundTrip(x, F2.class);
	}

}
