package com.googlecode.objectify.test;

import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.test.util.TestBase;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.google.common.truth.Truth.assertThat;
import static com.googlecode.objectify.ObjectifyService.factory;

/**
 */
class EmbeddedCollectionTests extends TestBase {

	@Entity
	@Data
	private static class HasSet {
		@Id private Long id;
		private Set<HashableThing> someSet = new HashSet<>();
	}

	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	private static class HashableThing {
		private Integer value;
	}

	@Test
	void setOfEmbeddedWorks() throws Exception {
		factory().register(HasSet.class);

		final HasSet has = new HasSet();
		has.someSet.add(new HashableThing(4));
		has.someSet.add(new HashableThing(5));
		has.someSet.add(new HashableThing(6));

		final HasSet fetched = saveClearLoad(has);

		assertThat(fetched.someSet).isEqualTo(has.someSet);
	}

	@Test
	void embeddedNullsWork() throws Exception {
		factory().register(HasSet.class);

		final HasSet has = new HasSet();
		has.someSet.add(null);

		final HasSet fetched = saveClearLoad(has);

		assertThat(fetched.someSet).isEqualTo(has.someSet);
	}

	/** Has an embed class in an embed collection */
	@Entity
	@Data
	private static class HasDeepThings {
		@Id
		private Long id;
		private List<DeepThing> deeps = new ArrayList<>();
	}

	/** */
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	private static class DeepThing {
		private HashableThing thing;
	}

	/** */
	@Test
	void testHasDeepThings() throws Exception {
		factory().register(HasDeepThings.class);

		final HasDeepThings has = new HasDeepThings();
		has.deeps.add(new DeepThing(new HashableThing(4)));
		has.deeps.add(new DeepThing(new HashableThing(5)));

		final HasDeepThings fetched = saveClearLoad(has);

		assertThat(fetched.deeps).isEqualTo(has.deeps);
	}
}

@@ -2116,11 +2116,473 @@
 eps);%0A%09%7D
+%0A%0A%09@Entity%0A%09@Data%0A%09private static class HasList %7B%0A%09%09@Id private Long id;%0A%09%09private List%3CHashableThing%3E someList = new ArrayList%3C%3E();%0A%09%7D%0A%0A%09@Test%0A%09void listsOfEntitiesPreserveOrder() throws Exception %7B%0A%09%09factory().register(HasList.class);%0A%0A%09%09final HasList has = new HasList();%0A%09%09for (int i = 0; i %3C 100; i++) %7B%0A%09%09%09has.someList.add(new HashableThing(i));%0A%09%09%7D%0A%0A%09%09final HasList fetched = saveClearLoad(has);%0A%0A%09%09assertThat(fetched.someList).isEqualTo(has.someList);%0A%09%7D
 %0A%7D%0A

Add test to verify that collections of embedded entities preserve order