/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

package com.queplix.core.modules.config.actions;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.modules.config.ejb.ContextMenuConfigManager;
import com.queplix.core.modules.config.ejb.ContextMenuConfigManagerHome;
import com.queplix.core.modules.config.jxb.ContextMenu;
import com.queplix.core.modules.config.jxb.ContextMenuForm;
import com.queplix.core.modules.config.jxb.ContextMenus;
import com.queplix.core.modules.config.jxb.MenuItem;
import com.queplix.core.modules.services.Action;
import com.queplix.core.modules.services.ServiceStartupManager;
import com.queplix.core.utils.JNDINames;
import com.queplix.core.utils.xml.XMLBinding;
import com.queplix.core.utils.xml.XMLFactory;
import com.queplix.core.utils.xml.XMLWrapper;
import org.w3c.dom.Document;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * <p>Action which parses config xml file(s) and fills ContextMenu EJBs</p>
 *
 * @author [MVT] Michael Trofimov
 */
public class ContextMenuInstallationAction extends Action {

    private Map<String, ContextMenu> contextMenuMap
            = new LinkedHashMap<String, ContextMenu>();

    /**
     * No javadoc
     */
    @Override
    public Serializable perform() {
        String[] contextMenuDirs = (String[]) getContext().getParameter(
                ServiceStartupManager.CONTEXTMENU_XML_DIR_PARAM);

        if(contextMenuDirs == null) {
            throw new NullPointerException("Parameter " + ServiceStartupManager
                    .CONTEXTMENU_XML_DIR_PARAM + " is NULL");
        }

        try {
            INFO("PROCESS STARTED...");
            long time = System.currentTimeMillis();

            parseContextMenus(contextMenuDirs);
            INFO("parse context menu configs - ok");

            buildContextMenus();
            INFO("build context menu configs - ok");

            deployContextMenus();
            INFO("deploy context menu configs - ok");

            INFO("Process last(s): "
                    + (System.currentTimeMillis() - time) / 1000);
            INFO("PROCESS DONE !!!");

        } catch (GenericSystemException ex) {
            ERROR(ex);
            throw ex;

        } catch (Exception ex) {
            ERROR(ex);
            throw new GenericSystemException(
                    "Unknown exception: " + ex.getMessage(), ex);
        }

        return null;
    }

    /**
     * Get FocusConfigManager EJB reference
     *
     * @return FocusConfigManager remote interface
     */
    private ContextMenuConfigManager getContextMenuConfigManager() {
        return (ContextMenuConfigManager) getContext().getCOM().getRemoteObject(
                JNDINames.ContextMenuConfigManagerRemote,
                ContextMenuConfigManagerHome.class);
    }

    private void deployContextMenus() {
        try {
            getContextMenuConfigManager().fillContextMenus(
                    contextMenuMap.values().toArray(
                            new ContextMenu[contextMenuMap.size()]));
        } catch (RemoteException e) {
            ERROR(e);
            throw new GenericSystemException(
                    "Remote exception. Can`t deploy focus configs: " + e
                            .getMessage(), e);
        }
    }

    private void buildContextMenus() {
        for(ContextMenu contextMenu : contextMenuMap.values()) {
            String contextMenuName = contextMenu.getName();
            int order = 0;
            for(MenuItem menuItem : contextMenu.getMenuItem()) {
                menuItem.setContextMenu(contextMenuName);
                menuItem.setOrder(order);
                order++;
            }
            for(ContextMenuForm menuForm : contextMenu.getContextMenuForm()) {
                menuForm.setContextMenu(contextMenuName);
            }
        }
    }

    private static final String CONFIG_FILES_EXTENSION = "xml";

    private void parseContextMenus(String[] contextMenuDirs) {
        for(String contextMenuDir : contextMenuDirs) {
            File contextMenuDirFile = new File(contextMenuDir);
            if(!contextMenuDirFile.exists() || !contextMenuDirFile
                    .isDirectory()) {
                ERROR("Bad context menu config dir: " + contextMenuDirFile
                        .getAbsolutePath());
            } else {
                // get list of files
                File[] files = contextMenuDirFile.listFiles(
                        new FilenameFilter() {
                            public boolean accept(File dir, String name) {
                                String ext = CONFIG_FILES_EXTENSION;
                                return name.substring(
                                        name.length() - ext.length()).equals(
                                        ext);
                            }
                        });
                try {
                    // cycle read focus config XML files
                    for(File file : files) {
                        INFO("  read from " + file.getCanonicalPath());
                        parseContextMenu(file);
                    }
                } catch (IOException ex) {
                    ERROR(ex);
                    throw new GenericSystemException(
                            "IO exception. Can't process parsing context menus: "
                                    + ex.getMessage(), ex);
                }
            }
        }
    }

    private void parseContextMenu(File contextMenuFile) {
        XMLWrapper xmlWrapper = XMLFactory.getXMLWrapper();
        XMLBinding xmlBind = XMLFactory.getXMLBinding();

        Document document = xmlWrapper.getDocument(contextMenuFile, false);
        ContextMenus contextMenus = (ContextMenus) xmlBind.xmlToJava(
                ContextMenus.class, document);

        for(ContextMenu contextMenu : contextMenus.getContextMenu()) {
            contextMenuMap.put(contextMenu.getName(), contextMenu);
        }
	}
}
