package it.mice.voila.runtime.hibernate.listeners;

import it.mice.voila.runtime.entity.Entity;
import it.mice.voila.runtime.hibernate.bag.CustomPersistentBag;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;


/**
 */
public class PreUpdateListener implements PreUpdateEventListener, PreInsertEventListener {
    private static Log logger = LogFactory.getLog(PreUpdateListener.class);

    private boolean useHibernateCascade = true;

    public boolean isUseHibernateCascade() {
        return useHibernateCascade;
    }

    public void setUseHibernateCascade(boolean useHibernateCascade) {
        this.useHibernateCascade = useHibernateCascade;
    }

    public boolean onPreUpdate(PreUpdateEvent event) {
        Entity entity = (Entity)event.getEntity();
        removeDeletedChildren(event);
        if (entity.isNewEntity()) {
            return false;
        }
        if (!entity.isChangedEntity()) {
            if (entity.isDeletedEntity()) {
                if (useHibernateCascade) {
                    ((Session)event.getSource()).delete(entity);
                } else {
                    event.getPersister().delete(event.getId(), null, entity, event.getSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Entity update discarded because not in changed internal status: " + entity);
            }
            return true;
        }
        return false;
    }

    public boolean onPreInsert(PreInsertEvent event) {
        Entity entity = (Entity)event.getEntity();
        if (!entity.isNewEntity()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Entity insert discarded because not in new internal status: " + entity);
            }
            return true;
        }
        return false;
    }

    private void removeDeletedChildren(PreUpdateEvent event) {
        Object[] o = event.getState();
        for (int i=0; i<o.length; i++) {
            if (o[i] instanceof CustomPersistentBag) {
                CustomPersistentBag bag = (CustomPersistentBag)o[i];
                bag.removeDeletedEntities();
            }
        }
    }
}
