package com.acme.model.domain.ejf.sessionbean;


import com.acme.model.domain.ejf.dao.EJFDao;
import com.acme.model.domain.ejf.entity.JobConfiguration;
import com.acme.model.domain.ejf.entity.Role;
import com.acme.model.domain.ejf.entity.RoleGroup;
import com.acme.structure.BaseFilter;
import com.acme.structure.GridData;
import com.acme.structure.PerformanceMonitor;
import com.acme.structure.ProfileInterceptor;
import com.acme.structure.ServerResponse;
import com.acme.structure.dao.MainDao;
import com.acme.structure.util.QuartzUtility;

import java.lang.reflect.InvocationTargetException;

import java.util.Collection;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;

import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

import javax.interceptor.Interceptors;

import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;


@Stateless(name="EJFManager", mappedName = "ejb/EJFManager/remote")
@TransactionManagement(TransactionManagementType.CONTAINER)
@Interceptors(value = { PerformanceMonitor.class, ProfileInterceptor.class })
public class EJFManagerBean implements EJFManager, EJFManagerLocal
{
    @PersistenceContext(unitName = "restmatic")
    private EntityManager manager;

    @Resource
    SessionContext ctx;

    private Logger logger = Logger.getLogger(this.getClass());

    MainDao dao = null;
    EJFDao ejfDao = null;

    @PostConstruct
    public void initialized()
    {
        dao = new MainDao();
        ejfDao = new EJFDao();

        dao.setEJBContext(ctx);
    }

    @RolesAllowed( { "sys", "sysmgr" })
    public Collection<JobConfiguration> findJobConfigurations(BaseFilter baseFilter) throws Exception
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        return dao.findByFilter(manager, baseFilter);
    }

    @RolesAllowed( { "sys", "sysmgr" })
    public Collection<JobConfiguration> findJobConfigurations() throws Exception
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        return dao.getEntityList(manager, new JobConfiguration());
    }

    @RolesAllowed( { "sysmgr" })
    public ServerResponse synchronizeJobConfigurations(GridData gridData) throws Exception
    {
        ServerResponse response = new ServerResponse();
        manager.setFlushMode(FlushModeType.COMMIT);

        Collection garbageData = gridData.getGarbageData();

        //remove garbage data
        for (Object object : garbageData)
        {
            JobConfiguration jobConfigurationToDelete = ((JobConfiguration)object);

            if (jobConfigurationToDelete.isPersisted())
                stopScheduler(jobConfigurationToDelete);
            dao.removeEntity(manager, jobConfigurationToDelete, true);
        }

        //save and create scheduler for only new data
        Collection updatedData = gridData.getNewBuffer();

        for (Object object : updatedData)
        {
            JobConfiguration jobConfigurationtoSave = ((JobConfiguration)object);

            createScheduler(jobConfigurationtoSave);
            jobConfigurationtoSave = (JobConfiguration)dao.saveOrUpdateEntity(manager, jobConfigurationtoSave);
            response.addData(jobConfigurationtoSave);
        }
        response.addDataList(gridData.getSynchBuffer());
        return response;
    }

    @RolesAllowed( { "sys", "sysmgr" })
    public ServerResponse createScheduler(JobConfiguration jobConf) throws Exception
    {
        ServerResponse response = new ServerResponse();
        try
        {
            QuartzUtility.createQuartzScheduler(jobConf.getJobName(), jobConf.getJndiName(), jobConf.getMethodName(), jobConf.getTriggerName(),
                                                jobConf.getCronExpression());

            logger.info("Quartz Scheduled Job - name : " + jobConf.getJobName() + " - trigger name : " + jobConf.getTriggerName() + " - cron expression : " +
                        jobConf.getCronExpression() + " !!! SUCCESSFULLY SCHEDULED !!! ");
        }
        catch (Exception exc)
        {
            logger.info("Problem SCHEDULING quartz job/saving JobConfiguration !!!");
            throw exc;
        }
        return response;
    }

    @RolesAllowed( { "sys", "sysmgr" })
    public ServerResponse stopScheduler(JobConfiguration jobConf) throws Exception
    {
        ServerResponse response = new ServerResponse();
        try
        {

            jobConf = (JobConfiguration)dao.findByPrimaryKey(manager, jobConf);
            QuartzUtility.stopQuartzScheduler(jobConf.getTriggerName());

            logger.info("Quartz Scheduled Job - name : " + jobConf.getJobName() + " - trigger name : " + jobConf.getTriggerName() + " - cron expression : " +
                        jobConf.getCronExpression() + " !!! SUCCESSFULLY UNSCHEDULED !!! ");
        }
        catch (Exception exc)
        {
            logger.info("Problem UNSCHEDULING quartz job/removing JobConfiguration !!!");
            throw exc;
        }
        return response;
    }

    public Collection findRoles()
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        Collection employees = dao.getEntityList(manager, new Role());
        return employees;
    }

    //@RolesAllowed( { "sys", "sysmgr" })
    public ServerResponse synchronizeRoles(GridData gridData) throws Exception
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        ServerResponse response = null;

        try
        {
            response = dao.synchronizeEntities(manager, gridData, false);
        }
        catch (Exception exc)
        {
            ctx.setRollbackOnly();
            throw exc;
        }

        return response;
    }

    public Collection findRolesForList()
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        return ejfDao.findRolesForList(manager);
    }

    public Collection findRoleGroups()
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        Collection employees = dao.getEntityList(manager, new RoleGroup());
        return employees;
    }

    public Collection findRoleGroupsForList()
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        return ejfDao.findRoleGroupsForList(manager);
    }
    
    //@RolesAllowed( { "sys", "sysmgr" })
    public ServerResponse synchronizeRoleGroups(GridData gridData) throws Exception
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        ServerResponse response = null;

        try
        {
            response = dao.synchronizeEntities(manager, gridData, false);
        }
        catch (Exception exc)
        {
            ctx.setRollbackOnly();
            throw exc;
        }

        return response;
    }

    public Collection findLogs(BaseFilter baseFilter) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
    {
        manager.setFlushMode(FlushModeType.COMMIT);
        return dao.findByFilter(manager, baseFilter, "findByfilterByTemplate");
    }
}
