package de.sb.messenger.rest;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.validation.constraints.NotNull;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import de.sb.messenger.persistence.Document;
import de.sb.messenger.persistence.Group;
import de.sb.messenger.persistence.Person;
import de.sb.toolbox.net.RestCredentials;

@Path("people")
public class PersonService {
	
	private static final EntityManager messengerManager = Persistence.createEntityManagerFactory("messenger").createEntityManager();

	@GET
	@Produces({ APPLICATION_JSON, APPLICATION_XML })
	public List<Person> queryPersons(@HeaderParam("Authorization") final String authentication,
		@QueryParam("givenName") final String givenName, @QueryParam("familyName") final String familyName,
		@QueryParam("mail") final String mail, @QueryParam("street") final String street,
		@QueryParam("postcode") final String postcode, @QueryParam("city") final String city, @QueryParam("group") final Group group) {
		TypedQuery<Person> query = messengerManager.createQuery("SELECT p FROM Person p WHERE "
				+ "(:givenName is null OR p.name.given = :givenName) AND "
				+ "(:familyName is null or p.name.family = :familyName) AND " 
				+ "(:mail IS null OR p.email = :mail) AND "
				+ "(:street IS null OR p.address.street = :street) AND "
				+ "(:postcode IS null OR p.address.postcode = :postcode) AND"
				+ "(:city IS null OR p.address.city = :city) AND"
				+ "(:group IS null OR p.group = :group)"
				+ " ORDER BY p.name.family, p.name.given, p.email",
				Person.class);
		List<Person> results = query
				.setParameter("mail", mail)
				.setParameter("givenName", givenName)
				.setParameter("familyName", familyName)
				.setParameter("street", street)
				.setParameter("postcode", postcode)
				.setParameter("city", city)
				.setParameter("group", group)
				.getResultList();
		if (results.isEmpty()) {
			throw new ClientErrorException(NOT_FOUND);
		}
		return results;
	}
	
	@GET
	@Path("{identity}")
	@Produces({ APPLICATION_JSON, APPLICATION_XML })
	public Person queryPerson(@HeaderParam("Authorization") final String authentication, @PathParam("identity") final long identity) {
		final EntityManager messengerManager = Persistence.createEntityManagerFactory("messenger").createEntityManager();
		Person person = messengerManager.find(Person.class, identity);
		if (person == null) {
			throw new ClientErrorException(NOT_FOUND);
		}
		return person;
	}
	
	@PUT
	@Consumes( {APPLICATION_JSON, APPLICATION_XML} )
	public long createPerson(@NotNull final Person person) {
		Person newPerson;
		final boolean insert = person.getIdentity() == 0;
		messengerManager.getTransaction().begin();
		System.out.println("INSERT: " + insert);
		if (insert) {
			Document avatar = messengerManager.find(Document.class, 1L);
			newPerson = new Person(avatar);
		} else {
			newPerson = messengerManager.find(Person.class, person.getIdentity());
		}
		System.out.println("Sent: " + person.getMail());
		newPerson.setMail(person.getMail());
		newPerson.setGroup(person.getGroup());
		newPerson.getAddress().setCity(person.getAddress().getCity());
		newPerson.getAddress().setPostcode(person.getAddress().getPostcode());
		newPerson.getAddress().setStreet(person.getAddress().getStreet());
		newPerson.getName().setFamily(person.getName().getFamily());
		newPerson.getName().setGiven(person.getName().getGiven());
		System.out.println("Created: " + person.getMail());
		
		try {
			if (insert) {
				messengerManager.persist(newPerson);
			} else {
				messengerManager.flush();				
			}
			messengerManager.getTransaction().commit();
		} catch(RuntimeException e) {
			e.printStackTrace();
		}
		
		return newPerson.getIdentity();
	}

	@GET
	@Path("{identity}/peopleObserving")
	@Produces({ APPLICATION_JSON, APPLICATION_XML })
	public List<Person> getPeopleObserving(@HeaderParam("Authorization") final String authentication, @PathParam("identity") final long identity){
		Authenticator.authenticate(RestCredentials.newBasicInstance(authentication));

		Person person = messengerManager.find(Person.class, identity);

		if (person == null) {
			throw new ClientErrorException(NOT_FOUND);
		}

		List<Person> peopleObserving = new ArrayList<>(person.getPeopleObserving());
		// TODO sort this list

		return peopleObserving;

	}

	@GET
	@Path("{identity}/peopleObserved")
	@Produces({ APPLICATION_JSON, APPLICATION_XML })
	public List<Person> getPeopleObserved(@HeaderParam("Authorization") final String authentication, @PathParam("identity") final long identity){
		Authenticator.authenticate(RestCredentials.newBasicInstance(authentication));

		Person person = messengerManager.find(Person.class, identity);

		if (person == null) {
			throw new ClientErrorException(NOT_FOUND);
		}
		List<Person> peopleObserved = new ArrayList<>(person.getPeopleObserved());

		// TODO sort this list

		return peopleObserved;
	}


}

@@ -367,16 +367,47 @@
 dQuery;%0A
+import javax.validation.Valid;%0A
 import j
@@ -3228,51 +3228,8 @@
 ();%0A
-%09%09System.out.println(%22INSERT: %22 + insert);%0A
 %09%09if
@@ -3432,59 +3432,8 @@
 %09%09%7D%0A
-%09%09System.out.println(%22Sent: %22 + person.getMail());%0A
 %09%09ne
@@ -3845,72 +3845,9 @@
 ;%0A%09%09
-System.out.println(%22Created: %22 + person.getMail());%0A%09%09%0A%09%09try %7B%0A%09
+%0A
 %09%09if
@@ -3858,17 +3858,16 @@
 sert) %7B%0A
-%09
 %09%09%09messe
@@ -3900,17 +3900,16 @@
 son);%0A%09%09
-%09
 %7D else %7B
@@ -3909,17 +3909,16 @@
  else %7B%0A
-%09
 %09%09%09messe
@@ -3944,20 +3944,18 @@
 ;%09%09%09%09%0A%09%09
-%09
 %7D%0A
-%09
 %09%09messen
@@ -3996,71 +3996,8 @@
 ();%0A
-%09%09%7D catch(RuntimeException e) %7B%0A%09%09%09e.printStackTrace();%0A%09%09%7D%0A%09%09%0A
 %09%09re

Remove debug code