package nl.idgis.publisher.admin;

import static nl.idgis.publisher.database.QGenericLayer.genericLayer;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import nl.idgis.publisher.domain.response.Page;
import nl.idgis.publisher.domain.response.Response;
import nl.idgis.publisher.domain.service.CrudOperation;
import nl.idgis.publisher.domain.service.CrudResponse;
import nl.idgis.publisher.domain.web.LayerGroup;
import nl.idgis.publisher.domain.web.QLayerGroup;
import akka.actor.ActorRef;
import akka.actor.Props;

import com.mysema.query.types.ConstantImpl;

public class LayerGroupAdmin extends AbstractAdmin {
	
	public LayerGroupAdmin(ActorRef database) {
		super(database); 
	}
	
	public static Props props(ActorRef database) {
		return Props.create(LayerGroupAdmin.class, database);
	}

	@Override
	protected void preStartAdmin() {
		addList(LayerGroup.class, this::handleListLayergroups);
		addGet(LayerGroup.class, this::handleGetLayergroup);
		addPut(LayerGroup.class, this::handlePutLayergroup);
		addDelete(LayerGroup.class, this::handleDeleteLayergroup);
	}

	private CompletableFuture<Page<LayerGroup>> handleListLayergroups () {
		log.debug ("handleListLayergroups");
		
		return 
			db.query().from(genericLayer)
			.list(new QLayerGroup(
					genericLayer.identification,
					genericLayer.name,
					genericLayer.title, 
					genericLayer.abstractCol,
					ConstantImpl.create(false)
				))
			.thenApply(this::toPage);
	}

	
	private CompletableFuture<Optional<LayerGroup>> handleGetLayergroup (String layergroupId) {
		log.debug ("handleGetLayergroup: " + layergroupId);
		
		return 
			db.query().from(genericLayer)
			.where(genericLayer.identification.eq(layergroupId))
			.singleResult(new QLayerGroup(
					genericLayer.identification,
					genericLayer.name,
					genericLayer.title, 
					genericLayer.abstractCol,
					ConstantImpl.create(false)
			));		
	}
	
	private CompletableFuture<Response<?>> handlePutLayergroup(LayerGroup theLayergroup) {
		String layergroupId = theLayergroup.id();
		String layergroupName = theLayergroup.name();
		log.debug ("handle update/create layergroup: " + layergroupId);
		
		return db.transactional(tx ->
			// Check if there is another layergroup with the same name
			tx.query().from(genericLayer)
			.where(genericLayer.identification.eq(layergroupId))
			.singleResult(genericLayer.identification)
			.thenCompose(msg -> {
				if (!msg.isPresent()){
					// INSERT
					log.debug("Inserting new layergroup with name: " + layergroupName);
					return tx.insert(genericLayer)
					.set(genericLayer.identification, UUID.randomUUID().toString())
					.set(genericLayer.name, layergroupName)
					.set(genericLayer.title, theLayergroup.title())
					.set(genericLayer.abstractCol, theLayergroup.abstractText())
					.execute()
					.thenApply(l -> new Response<String>(CrudOperation.CREATE, CrudResponse.OK, layergroupName));
				} else {
					// UPDATE
					log.debug("Updating layergroup with name: " + layergroupName);
					return tx.update(genericLayer)
							.set(genericLayer.title, theLayergroup.title())
							.set(genericLayer.abstractCol, theLayergroup.abstractText())
					.where(genericLayer.identification.eq(layergroupId))
					.execute()
					.thenApply(l -> new Response<String>(CrudOperation.UPDATE, CrudResponse.OK, layergroupName));
				}
		}));
	}

	private CompletableFuture<Response<?>> handleDeleteLayergroup(String layergroupId) {
		log.debug ("handleDeleteLayergroup: " + layergroupId);
		return db.delete(genericLayer)
			.where(genericLayer.identification.eq(layergroupId))
			.execute()
			.thenApply(l -> new Response<String>(CrudOperation.DELETE, CrudResponse.OK, layergroupId));
	}
	
}

@@ -100,16 +100,81 @@
 cLayer;%0D
+%0Aimport static nl.idgis.publisher.database.QLeafLayer.leafLayer;%0D
 %0A%0D%0Aimpor
@@ -1328,28 +1328,24 @@
 rgroups%22);%0D%0A
-%09%09%0D%0A
 %09%09return %0D%0A%09
@@ -1373,24 +1373,144 @@
 ericLayer)%0D%0A
+%09%09%09.leftJoin(leafLayer).on(genericLayer.id.eq(leafLayer.genericLayerId))%0D%0A%09%09%09.where(leafLayer.genericLayerId.isNull())%0D%0A
 %09%09%09.list(new
@@ -1652,34 +1652,30 @@
 %09%09%09%09
-ConstantImpl.create(false)
+genericLayer.published
 %0D%0A%09%09
@@ -1860,36 +1860,32 @@
 layergroupId);%0D%0A
-%09%09%0D%0A
 %09%09return %0D%0A%09%09%09db
@@ -2133,34 +2133,30 @@
 %09%09%09%09
-ConstantImpl.create(false)
+genericLayer.published
 %0D%0A%09%09
@@ -3072,24 +3072,86 @@
 actText())%0D%0A
+%09%09%09%09%09.set(genericLayer.published, theLayergroup.published())%0D%0A
 %09%09%09%09%09.execut
@@ -3512,24 +3512,88 @@
 actText())%0D%0A
+%09%09%09%09%09%09%09.set(genericLayer.published, theLayergroup.published())%0D%0A
 %09%09%09%09%09.where(
@@ -3769,32 +3769,32 @@
 %0D%0A%09%09%7D));%0D%0A%09%7D%0D%0A%0D%0A
-
 %09private Complet
@@ -3856,32 +3856,100 @@
 ayergroupId) %7B%0D%0A
+%09%09// TODO remove from layerStructure if present in parent or child%0D%0A
 %09%09log.debug (%22ha

handle published field in group