package placebooks.services;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

import org.apache.log4j.Logger;

import placebooks.model.LoginDetails;
import placebooks.model.PlaceBookItem;
import placebooks.model.User;

public abstract class Service
{
	private static final Logger log = Logger.getLogger(Service.class);
	
	protected abstract void sync(EntityManager manager, User user, LoginDetails details);
	
	public abstract boolean checkLogin(final String username, final String password);
	
	public void sync(EntityManager manager, final User user, boolean force)
	{
		final LoginDetails details = user.getLoginDetails(getName());

		if (details == null)
		{
			log.error("Service for " + this.getName() + " import failed, login details null");
			return;
		}
		if(details.isSyncInProgress())
		{
			log.info(details.getService() +  " sync already in progress");
			return;			
		}
		else
		{
			log.info(details.getService() +  " sync starting");
			manager.getTransaction().begin();
			details.setSyncInProgress(true);
			manager.merge(details);
			manager.getTransaction().commit();			
		}
		if(!force && details.getLastSync() != null)
		{
			log.info("Last sync of " + getName()  + ": " + details.getLastSync());
			final Calendar calendar = Calendar.getInstance();
			calendar.set(Calendar.HOUR_OF_DAY, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND,0);
			if(calendar.getTime().before(details.getLastSync()))
			{
				log.debug("Not syncing " + getName()  + " automatically as last sync date was today.");
				return;
			}		
		}

		try
		{
			sync(manager, user, details);
		}
		finally
		{
			manager.getTransaction().begin();
			details.setSyncInProgress(false);
			manager.merge(details);
			manager.getTransaction().commit();
			log.info("Synced " + getName() +": " + details.getLastSync());			
		}
	}
	
	public abstract String getName();
	
	public int cleanupItems(EntityManager manager, ArrayList<String> itemsToKeep, User user)
	{
		log.debug("Starting cleanup for " + getName() + " " + itemsToKeep.size() + " items to keep");
		int deletedItems = 0;
		try
		{
			manager.getTransaction().begin();
			TypedQuery<PlaceBookItem> q = manager.createQuery("SELECT placebookitem FROM PlaceBookItem AS placebookitem " +
					" WHERE (placebookitem.owner = ?1) AND (placebookitem.placebook IS null)", PlaceBookItem.class);
			q.setParameter(1, user);
			Collection<PlaceBookItem> items = q.getResultList();
			for(PlaceBookItem placebookitem: items)
			{
				if(placebookitem.getMetadataValue("source").equals(getName()))
				{
					if(itemsToKeep.contains(placebookitem.getExternalID()))
					{
						log.debug("Keeping item: " + placebookitem.getExternalID() + " id: " + placebookitem.getKey());
					}
					else
					{
						log.debug("Removing item: " + placebookitem.getExternalID() + " id: " + placebookitem.getKey());
						manager.remove(placebookitem);
						deletedItems++;
					}
				}
			}
			manager.getTransaction().commit();
		}
		finally
		{
			if (manager.getTransaction().isActive())
			{
				manager.getTransaction().rollback();
				log.error("Rolling " + getName() +" cleanup back");
			}
		}	
		return deletedItems;
	}
	
}

@@ -906,19 +906,33 @@
 %0A%09%09%7D%0D%0A%09%09
-if(
+%0D%0A%09%09if(!force && 
 details.
@@ -1048,225 +1048,10 @@
 %09%7D%0D%0A
+
 %09%09
-else%0D%0A%09%09%7B%0D%0A%09%09%09log.info(details.getService() +  %22 sync starting%22);%0D%0A%09%09%09manager.getTransaction().begin();%0D%0A%09%09%09details.setSyncInProgress(true);%0D%0A%09%09%09manager.merge(details);%0D%0A%09%09%09manager.getTransaction().commit();%09%09%09%0D%0A%09%09%7D
 %0D%0A%09%09
@@ -1574,16 +1574,240 @@
 %0A%09%09%7D%0D%0A%0D%0A
+%09%09log.info(details.getService() +  %22 sync starting%22);%0D%0A%09%09manager.getTransaction().begin();%0D%0A%09%09details.setSyncInProgress(true);%0D%0A%09%09details.setLastSync();%0D%0A%09%09manager.merge(details);%0D%0A%09%09manager.getTransaction().commit();%09%09%09%0D%0A%0D%0A
 %09%09try%0D%0A%09

Improve sync