package org.sculptor.examples.library.person.domain;

import java.util.Calendar;
import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.sculptor.examples.library.person.domain.Gender;
import org.sculptor.examples.library.person.domain.PersonBase;
import org.sculptor.examples.library.person.domain.Ssn;
import org.sculptor.framework.errorhandling.ValidationException;

/**
 *
 * Entity representing Person. This class is responsible for the domain object
 * related business logic for Person. Properties and associations are
 * implemented in the generated base class
 * {@link org.sculptor.examples.library.person.domain.PersonBase}
 * .
 */
@Entity(name = "Person")
@Table(name = "PERSON", uniqueConstraints = @UniqueConstraint(columnNames = { "SSN_NUMBER", "SSN_COUNTRY" }))
@NamedQueries( {
        @NamedQuery(name = "Person.findByCountry", query = "select person from Person person where person.ssn.country = :country", hints = {
                @QueryHint(name = "org.hibernate.cacheable", value = "true"),
                @QueryHint(name = "org.hibernate.cacheRegion", value = "query.Person") }),
        @NamedQuery(name = "Person.countByCountry", query = "select count(person) from Person person where person.ssn.country = :country", hints = {
                @QueryHint(name = "org.hibernate.cacheable", value = "true"),
                @QueryHint(name = "org.hibernate.cacheRegion", value = "query.Person") }),
        @NamedQuery(name = "Person.findPersonByName", query = "select person from Person person where person.name.first in :names or person.name.last in :names") })

// datanucleus needs '(:names)' in where clause
// @NamedQuery(name = "Person.findPersonByName", query = "select person from Person person where person.name.first in (:names) or person.name.last in (:names)")

public class Person extends PersonBase {
	private static final long serialVersionUID = -3936470509835260676L;

	protected Person() {
	}

	public Person(Gender sex, Ssn ssn) {
		super(sex, ssn);
	}

	@Override
	public void setBirthDate(LocalDate birthDate) {
		if (birthDate != null && birthDate.isAfter(LocalDate.now())) {
			throw new ValidationException("birthDate is in past");
		}
		super.setBirthDate(birthDate);
	}

	public Integer getAge() {
		LocalDate bd = getBirthDate();
		if (bd == null) {
			return null;
		}

		LocalDate now = LocalDate.now();
		int age = now.getYear() - bd.getYear();

		if (bd.withYear(now.getYear()).isAfter(now)) {
			age -= 1;
		}

		return age;
	}
}
