package com.nurkiewicz.java8;

import com.nurkiewicz.java8.people.Person;
import org.junit.Ignore;
import org.junit.Test;

import java.time.LocalDate;
import java.time.Month;
import java.util.Optional;

import static com.nurkiewicz.java8.people.Sex.MALE;
import static org.fest.assertions.api.Assertions.assertThat;

/**
 * Transform old-fashioned code using nulls with Optional
 * Hint: use map/filter/flatMap/ifPresent
 */
@Ignore
public class J06_OptionalTest {

	private Person findPersonOrNull(int id) {
		if (id > 0) {
			return new Person("James", MALE, 62, 169, LocalDate.of(1970 + id, Month.DECEMBER, 21));
		} else {
			return null;
		}
	}

	private String lookupAddressOrNull(Person person) {
		if (person.getDateOfBirth().isAfter(LocalDate.of(1993, Month.JANUARY, 1))) {
			return "Some St.  ";
		} else {
			return null;
		}
	}

	private String lookupAddressByIdOrNull(int id) {
		final Person personOrNull = findPersonOrNull(id);
		if (personOrNull != null) {
			if (personOrNull.getSex() == MALE) {
				final String addressOrNull = lookupAddressOrNull(personOrNull);
				if (addressOrNull != null && !addressOrNull.isEmpty()) {
					return addressOrNull.trim();
				} else {
					return null;
				}
			}
		}
		return null;
	}

	/**
	 * Don't change, call from {@link #tryLookupAddressById(int)}
	 */
	private Optional<Person> tryFindPerson(int id) {
		return Optional.ofNullable(findPersonOrNull(id));
	}

	/**
	 * Don't change, call from {@link #tryLookupAddressById(int)}
	 */
	private Optional<String> tryLookupAddress(Person person) {
		return Optional.ofNullable(lookupAddressOrNull(person));
	}

	/**
	 * TODO: Copy and refactor code from {@link #lookupAddressByIdOrNull}, but avoid nulls
	 */
	private Optional<String> tryLookupAddressById(int id) {
		return Optional.empty(); // tryFindPerson(id).
	}

	@Test
	public void nulls() {
		assertThat(lookupAddressByIdOrNull(-1)).isNull();
		assertThat(lookupAddressByIdOrNull(21)).isNull();
		assertThat(lookupAddressByIdOrNull(41)).isEqualTo("Some St.");
	}

	@Test
	public void optionals() {
		assertThat(tryLookupAddressById(-1).isPresent()).isFalse();
		assertThat(tryLookupAddressById(21).isPresent()).isFalse();
		assertThat(tryLookupAddressById(41).get()).isEqualTo("Some St.");
	}

}

@@ -472,58 +472,258 @@
 ate 
-Person findPersonOrNull(int id) %7B%0A%09%09if (id %3E 0) %7B%0A
+static final int PERSON_ID_WITH_NO_ADDRESS = 1;%0A%09private static final int PERSON_ID_WITH_ADDRESS = 2;%0A%09private static final int UNAVAILABLE_PERSON_ID = 0;%0A%0A%09private Person findPersonOrNull(int id) %7B%0A%09%09switch(id) %7B%0A%09%09%09case PERSON_ID_WITH_NO_ADDRESS:%0A%09
 %09%09%09r
@@ -780,17 +780,12 @@
 .of(
-1970 + id
+2007
 , Mo
@@ -802,33 +802,201 @@
 ER, 21));%0A%09%09
+%09
-%7D else %7B%0A
+case PERSON_ID_WITH_ADDRESS:%0A%09%09%09%09return new Person(%22John%22, MALE, 62, 169, LocalDate.of(1985, Month.DECEMBER, 21));%0A%09%09%09case UNAVAILABLE_PERSON_ID:%0A%09%09%09%09return null;%0A%09%09%09default:%0A%09
 %09%09%09return nu
@@ -1115,12 +1115,109 @@
 .of(
-1993
+2000, Month.JANUARY, 1))) %7B%0A%09%09%09return %22%22;%0A%09%09%7D%0A%09%09if (person.getDateOfBirth().isAfter(LocalDate.of(1980
 , Mo
@@ -1247,16 +1247,17 @@
 return %22
+ 
 Some St.
@@ -1262,23 +1262,16 @@
 t.  
+ 
 %22;%0A%09%09%7D
- else %7B%0A%09
+%0A
 %09%09re
@@ -1273,36 +1273,32 @@
 %0A%09%09return null;%0A
-%09%09%7D%0A
 %09%7D%0A%0A%09private Str
@@ -2335,18 +2335,37 @@
 dOrNull(
--1
+UNAVAILABLE_PERSON_ID
 )).isNul
@@ -2406,18 +2406,41 @@
 dOrNull(
-21
+PERSON_ID_WITH_NO_ADDRESS
 )).isNul
@@ -2481,18 +2481,38 @@
 dOrNull(
-41
+PERSON_ID_WITH_ADDRESS
 )).isEqu
@@ -2605,10 +2605,29 @@
 yId(
--1
+UNAVAILABLE_PERSON_ID
 ).is
@@ -2682,18 +2682,41 @@
 essById(
-21
+PERSON_ID_WITH_NO_ADDRESS
 ).isPres
@@ -2771,10 +2771,30 @@
 yId(
-41
+PERSON_ID_WITH_ADDRESS
 ).ge

Make sure filtering out empty addresses is tested