package de.hsadmin.mods.email;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import de.hsadmin.core.model.AbstractEntity;
import de.hsadmin.core.qserv.CompoundProcessor;
import de.hsadmin.core.qserv.EntityProcessorFactory;
import de.hsadmin.core.qserv.Processor;
import de.hsadmin.core.qserv.ShellProcessor;

/**
 * System level implementation for EMailAdress module.
 */
public class EMailAddressProcessorFactory implements EntityProcessorFactory {
	
	/**
	 * @return a Processor which creates an email address
	 */
	public <T extends AbstractEntity> Processor createCreateProcessor(EntityManager em, T entity) {
		// TODO: combine both keys in a single call (optimization)
		EMailAddress email = (EMailAddress) entity;
		CompoundProcessor cp = new CompoundProcessor();
		cp.appendProcessor(new ShellProcessor( "postmap -r -i /etc/postfix/virtual",
				email.getFullDomain() + " -" ) );
		cp.appendProcessor(new ShellProcessor( "postmap -r -i /etc/postfix/virtual",
				email.getEMailAddress() + " " + email.getTarget() ) );
		return cp;
	}
	
	/**
	 * @return a Processor which updates an email address 
	 */
	public <T extends AbstractEntity> Processor createUpdateProcessor(EntityManager em, T entity) {
		// TODO: if update is specified by primary-key or DB query instead of OID,
		// 	a  postmap -d might be neccessary 
		return createCreateProcessor(em, entity);
	}
	
	/**
	 * @return a Processor which deletes an email address
	 */
	public <T extends AbstractEntity> Processor createDeleteProcessor(EntityManager em, T entity) {
		// TODO: combine both keys in a single call (optimization)
		// remove the entry itself
		CompoundProcessor cp = new CompoundProcessor();
		EMailAddress email = (EMailAddress) entity;
		cp.appendProcessor( 
				new ShellProcessor( "postmap -d '" + email.getEMailAddress() + "' /etc/postfix/virtual" ) );
		// any other email addresses for this domain?
		Query query;
		if ( email.getSubdomain() != null ) {
			query = em.createQuery("SELECT e FROM EMailAddresses e WHERE e.subdomain=:subdomain AND e.domain=:domain");
			query.setParameter("subdomain", email.getSubdomain());
		}
		else {
			query = em.createQuery("SELECT e FROM EMailAddresses e WHERE e.subdomain IS NULL AND e.domain=:domain");
		}
		query.setParameter("domain", email.getDomain());
		List<?> result = query.getResultList();
		if ( result == null || result.size() == 0 ) {
			// remove the domain from virtual.db
			cp.appendProcessor( 
					new ShellProcessor( "postmap -d '" + email.getFullDomain() + "' /etc/postfix/virtual" ) );
		}
		return cp;
	}
}
