package de.hsadmin.mods.pac;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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

import de.hsadmin.core.model.AbstractEntity;
import de.hsadmin.core.model.AbstractModuleImpl;
import de.hsadmin.core.model.AuthorisationException;
import de.hsadmin.core.model.HSAdminException;
import de.hsadmin.core.util.TextUtil;
import de.hsadmin.mods.cust.Contact;
import de.hsadmin.mods.cust.Customer;
import de.hsadmin.mods.user.UnixUser;

public class PacModuleImpl extends AbstractModuleImpl {

	@Override
	public List<AbstractEntity> search(Class<? extends AbstractEntity> entityClass,
			String condition, String orderBy) throws HSAdminException {
		if (orderBy == null || orderBy.length() == 0) {
			orderBy = "ORDER BY obj.name ASC";
		}
		return super.search(entityClass, condition, orderBy);
	}

	@Override
	public AbstractEntity add(AbstractEntity newEntity) throws HSAdminException {
		EntityManager em = getTransaction().getEntityManager();
		Pac pac = (Pac) newEntity;
		Date now = new Date();
		pac.setCreated(now);
		BasePac basepac = pac.getBasepac();
		if (basepac == null || basepac.getName() == null || basepac.getName().length() == 0) {
			throw new HSAdminException("basepac required");
		}
		Query qBasepac = em.createQuery("SELECT b FROM BasePacs b WHERE b.name = :basepacName AND b.valid = :valid");
		qBasepac.setParameter("basepacName", basepac.getName());
		qBasepac.setParameter("valid", Boolean.TRUE);
		basepac = (BasePac) qBasepac.getSingleResult();
		pac.setBasepac(basepac);
		INetAddress curINetAddr = pac.getCurINetAddr();
		if (curINetAddr == null || curINetAddr.getInetAddr() == null || curINetAddr.getInetAddr().length() == 0) {
			throw new HSAdminException("curinetaddr required");
		}
		Query qINetAddr = em.createNativeQuery("SELECT * FROM inet_addr WHERE inet_addr = inet '" + curINetAddr.getInetAddr() + "'", INetAddress.class);
		curINetAddr = (INetAddress) qINetAddr.getSingleResult();
		pac.setCurINetAddr(curINetAddr);
		Customer customer = pac.getCustomer();
		if (customer == null || customer.getName() == null || customer.getName().length() == 0) {
			throw new HSAdminException("customer required");
		}
		Query qCustomer = em.createQuery("SELECT c FROM Customers c WHERE c.name = :name");
		qCustomer.setParameter("name", customer.getName());
		customer = (Customer) qCustomer.getSingleResult();
		pac.setCustomer(customer);
		Hive hive = pac.getHive();
		if (hive == null || hive.getName() == null || hive.getName().length() == 0) {
			throw new HSAdminException("hive required");
		}
		Query qHive = em.createQuery("SELECT h FROM Hives h WHERE h.name = :name");
		qHive.setParameter("name", hive.getName());
		hive = (Hive) qHive.getSingleResult();
		pac.setHive(hive);
		Query qComponents = em.createQuery("SELECT c FROM Components c WHERE c.basePacId = :basepac");
		qComponents.setParameter("basepac", basepac.id());
		List<?> componentsList = qComponents.getResultList();
		Set<PacComponent> pacComponents = new HashSet<PacComponent>();
		for (Object cObj : componentsList) {
			Component comp = (Component) cObj;
			PacComponent pacComponent = new PacComponent();
			pacComponent.setBaseComponent(comp.getBaseComponent());
			pacComponent.setbasePac(comp.getBasePac());
			pacComponent.setCreated(now);
			pacComponent.setPac(pac);
			pacComponent.setQuantity(comp.getDefaultQuantity());
			pacComponents.add(pacComponent);
		}
		pac.setPacComponents(pacComponents);
		Set<UnixUser> users = new HashSet<UnixUser>();
		pac.setUnixUser(users);
		UnixUser admin = new UnixUser();
		Contact contact = customer.getContractualContact();
		admin.setComment(TextUtil.replaceUmlautCharacters(contact.getFirstName() + " " + contact.getLastName()));
		admin.setHomedir("/home/pacs/" + pac.getName());
		admin.setName(pac.getName());
		admin.setShell("/bin/bash");
		admin.setQuotaSoftlimit(0);
		admin.setQuotaHardlimit(0);
		admin.setPac(pac);
		long nUID = 20000;
		Long maxUid = (Long) em.createQuery("SELECT MAX(u.userId) FROM UnixUsers u").getSingleResult();
		if (maxUid >= nUID) nUID = maxUid + 1;
		admin.setUserId(nUID);
		return super.add(newEntity);
	}

	@Override
	public AbstractEntity update(AbstractEntity existingEntity)
			throws HSAdminException {
		throw new AuthorisationException(getLoginUser(), "update", existingEntity);
	}
	
}
