package org.ow2.jonas.lib.management.extensions.container;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.ow2.jonas.lib.management.extensions.base.BaseManagement;
import org.ow2.jonas.lib.management.extensions.base.JonasManagementRepr;
import org.ow2.jonas.lib.management.extensions.container.ejb.EjbItem;
import org.ow2.jonas.lib.management.extensions.container.ejb.EjbItemByNameComparator;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.management.extensions.container.api.IContainerManagement;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

public class ContainerManagement implements IContainerManagement {

    /**
     * create logger
     */
    protected static Log logger = LogFactory.getLog(ContainerManagement.class);

    /**
     * singleton instance.
     */
    private static ContainerManagement unique = null;

    /**
     * Default constructor.
     */
    public ContainerManagement() {
        // TODO Auto-generated constructor stub
    }

    /**
     * Get singleton instance.
     * @return singleton instance.
     */
    public static IContainerManagement getInstance() {
        if (unique == null) {
            unique = new ContainerManagement();
        }
        return unique;
    }

    /**
     * Gets ObjectName for J2EE Module.
     * @param ejbObjectName
     * @return module objectName.
     * @throws MalformedObjectNameException
     */
    public ObjectName getEJBModuleObjectName(final String ejbObjectName) throws MalformedObjectNameException {
        ObjectName o_ejbObjectName = new ObjectName(ejbObjectName);
        String domainName = o_ejbObjectName.getDomain();
        String moduleName = o_ejbObjectName.getKeyProperty("EJBModule");
        String serverName = o_ejbObjectName.getKeyProperty("J2EEServer");
        String appName = o_ejbObjectName.getKeyProperty("J2EEApplication");
        return J2eeObjectName.getEJBModule(domainName, serverName, appName, moduleName);
    }

    /**
     * Gets all the EntityBean MBeans in a module which is deployed in a given
     * server
     * @param pDomain domain name
     * @param pModule name of the module containing the Entity
     * @param pServer the server name
     * @return List of entity beans.
     */
    public List<?> getEntityBeans(final ObjectName pObjectName, final String serverName) {
        ONameAttrib onAttr = new ONameAttrib(pObjectName);
        ObjectName on = J2eeObjectName.getEntityBeans(onAttr.getDomainName(), onAttr.getModuleName(), onAttr.getServerName());
        return beanItems(on, onAttr.getServerName());

    }

    /**
     * Gets all the Stateless Session MBeans in a module which is deployed in a
     * given server
     * @param pObjectName pObjectName
     * @param serverName name of the administrated server.
     * @return List of entity beans.
     */
    public List<?> getStatelessSessionBeans(final ObjectName pObjectName, final String serverName) {
        ONameAttrib onAttr = new ONameAttrib(pObjectName);
        ObjectName on = J2eeObjectName.getStatelessSessionBeans(onAttr.getDomainName(), onAttr.getModuleName(),
                onAttr.getServerName());
        return beanItems(on, onAttr.getServerName());
    }

    /**
     * Gets all the Stateful Session MBeans in a module which is deployed in a
     * given server
     * @param pObjectName pObjectName
     * @param serverName name of the administrated server.
     * @return List of entity beans.
     */
    public List<?> getStatefulSessionBeans(final ObjectName pObjectName, final String serverName) {
        ONameAttrib onAttr = new ONameAttrib(pObjectName);
        ObjectName on = J2eeObjectName.getStatefulSessionBeans(onAttr.getDomainName(), onAttr.getModuleName(),
                onAttr.getServerName());
        return beanItems(on, onAttr.getServerName());
    }

    /**
     * Gets all the Message Driven MBeans in a module which is deployed in a
     * given server
     * @param pObjectName pObjectName
     * @param serverName name of the administrated server.
     * @return List of entity beans.
     */
    public List<?> getMessageDrivenBeans(final ObjectName pObjectName, final String serverName) {
        ONameAttrib onAttr = new ONameAttrib(pObjectName);
        ObjectName on = J2eeObjectName.getMessageDrivenBeans(onAttr.getDomainName(), onAttr.getModuleName(),
                onAttr.getServerName());
        return beanItems(on, onAttr.getServerName());
    }
    /**
     *
     * @param on the objectName.
     * @param serverName the server wher the objectName is registrated.
     * @return baen items.
     */
    private List<?> beanItems(final ObjectName on, final String serverName) {
        ArrayList<EjbItem> al = new ArrayList<EjbItem>();
        Iterator<?> itNames = BaseManagement.getInstance().getListMbean(on, serverName).iterator();
        while (itNames.hasNext()) {
            try {
                al.add(new EjbItem(new ObjectName((String)itNames.next()), serverName));
            } catch (Exception e) {
                logger.debug("Exception in beanItems", e);
            }

        }
        Collections.sort(al, new EjbItemByNameComparator());
        return al;
    }

    /**
     * Private utility class. Used to avoid code duplication.
     * @author eyindanga
     */
    private class ONameAttrib {
        /**
         * Domain name.
         */
        private String domainName;

        /**
         * Server name.
         */
        private String serverName;

        /**
         * module name.
         */
        private String moduleName;

        /**
         * Default constructor.
         */
        public ONameAttrib() {
            // TODO Auto-generated constructor stub
        }

        /**
         * Default constructor.
         */
        public ONameAttrib(final ObjectName pObjectName) {
            domainName = pObjectName.getDomain();
            serverName = pObjectName.getKeyProperty("J2EEServer");
            moduleName = pObjectName.getKeyProperty("name");
        }

        /**
         * Gets domain name.
         * @return domain name.
         */
        public String getDomainName() {
            return domainName;
        }

        /**
         * Gets server name.
         * @return server name.
         */
        public String getServerName() {
            return serverName;
        }

        /**
         * Gets module name.
         * @return module name.
         */
        public String getModuleName() {
            return moduleName;
        }

    }

    /**
     * Get the total number of EJBs in a EJBModule
     * @param moduleOn the EJBModule's ObjectName
     * @return map with the number of EJBs of different types where the key is the JSR77 type name
     */
    public Map getTotalEJB(final ObjectName moduleOn) {
        HashMap<String, Integer> table = new HashMap<String, Integer>();
        int nbStatefulSessionBean = 0;
        int nbStatelessSessionBean = 0;
        int nbEntityBean = 0;
        int nbMessageDrivenBean = 0;
        String serverName = moduleOn.getKeyProperty("J2EEServer");
        String[] ejbs = (String[]) JonasManagementRepr.getAttribute(moduleOn, "ejbs", serverName);
        for (int i = 0; i < ejbs.length; i++) {
            String ejbON = ejbs[i];
            try {
                ObjectName ejbOn = ObjectName.getInstance(ejbON);
                String ejbType = ejbOn.getKeyProperty("j2eeType");
                if ("StatefulSessionBean".equals(ejbType)) {
                    nbStatefulSessionBean++;
                } else if ("StatelessSessionBean".equals(ejbType)) {
                    nbStatelessSessionBean++;
                } else if ("EntityBean".equals(ejbType)) {
                    nbEntityBean++;
                } else if ("MessageDrivenBean".equals(ejbType)) {
                    nbMessageDrivenBean++;
                }
            } catch (MalformedObjectNameException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NullPointerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        table.put("StatefulSessionBean", nbStatefulSessionBean);
        table.put("StatelessSessionBean", nbStatelessSessionBean);
        table.put("EntityBean", nbEntityBean);
        table.put("MessageDrivenBean", nbMessageDrivenBean);
        return table;
    }

}
