/*
 * 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.services;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.integrator.security.LogonSession;
import com.queplix.core.modules.config.actions.ContextMenuInstallationAction;
import com.queplix.core.modules.config.actions.CustomInstallationAction;
import com.queplix.core.modules.config.actions.EntityInstallationAction;
import com.queplix.core.modules.config.actions.FormInstallationAction;
import com.queplix.core.modules.config.actions.PortalConfigInstallationAction;
import com.queplix.core.modules.config.actions.SystemChartsInstallationAction;
import com.queplix.core.modules.services.actions.ScriptInstallationAction;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * <p>Startup QW services (scheduler and tools) manager</p>
 *
 * @author Baranov Andrey [ALB]
 * @version $Revision: 1.1 $ $Date: 2006/04/18 12:04:16 $
 */

public final class ServiceStartupManager {

    // ----------------------------------------------------- constants

    public static final String ENTITY_XML_DIR_PARAM = "xmldir";
    public static final String ENTITY_XSL_DIR_PARAM = "xsldir";
    public static final String FOCUS_XML_DIR_PARAM = "focusdir";
    public static final String CONTEXTMENU_XML_DIR_PARAM = "contextmenudir";
    public static final String SYSTEM_CHARTS_XML_DIR_PARAM = "systemChartsDir";
    
    public static final String SCRIPT_XML_FILE_PARAM = "scriptfile";
    public static final String PORTAL_CONFIG_FILE_PARAM = "portal";
    public static final String CUSTOM_XML_DIR_PARAM = "customdir";
    public static final String I18N_XML_DIR_PARAM = "i18ndir";

    private static final AbstractLogger logger = Log.getLog(
            ServiceStartupManager.class);

    // ----------------------------------------------------- public methods

    /**
     * Runs the Entity Installation Tool.
     *
     * @param ls user logon session
     */
    public static void runEntityTool(LogonSession ls, ServiceInitManager sim) {
        runEntityTool(ls, new ServiceInitManager[]{sim});
    }

    /**
     * Runs the Entity Installation Tool.
     *
     * @param ls user logon session
     */
    public static void runEntityTool(LogonSession ls,
                                     ServiceInitManager[] sims) {
        ActionContext context = new ActionContext(ls);
        String[] entityDirs = new String[sims.length];
        for(int i = 0; i < sims.length; i++) {
            entityDirs[i] = sims[i].getEntityXmlDir();
        }
        context.addParameter(EntityInstallationAction.ENTITY_XML_DIRS_PARAM,
                entityDirs);

        ActionRunner.run(new EntityInstallationAction(), context);
    }

    /**
     * Runs the Form Installation Tool.
     *
     * @param ls           user logon session
     * @param focusXmlDirs focus xml dirs
     */
    public static void runFocusTool(LogonSession ls, String[] focusXmlDirs) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(FOCUS_XML_DIR_PARAM, focusXmlDirs);

        ActionRunner.run(new FormInstallationAction(), context);
    }

    /**
     * Runs the ContextMenu Installation Tool.
     *
     * @param ls                 user logon session
     * @param contextMenuXmlDirs contextMenu xml dirs
     */
    public static void runContextMenuTool(LogonSession ls,
                                          String[] contextMenuXmlDirs) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(CONTEXTMENU_XML_DIR_PARAM, contextMenuXmlDirs);

        ActionRunner.run(new ContextMenuInstallationAction(), context);
    }

    /**
     * Runs the System Charts Installation Tool.
     *
     * @param ls  user logon session
     * @param sim TODO
     */
    public static void runSystemChartsTool(LogonSession ls, String[] chartsXmlDirs) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(SYSTEM_CHARTS_XML_DIR_PARAM, chartsXmlDirs);

        ActionRunner.run(new SystemChartsInstallationAction(), context);
    }
    
    public static void runPortalTools(LogonSession ls, File portalCongfigFile) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(PORTAL_CONFIG_FILE_PARAM, portalCongfigFile);
        ActionRunner.run(new PortalConfigInstallationAction(), context);
    }

    /**
     * Runs the Script Installation Tool.
     *
     * @param ls  user logon session
     * @param sim TODO
     */
    public static void runScriptTool(LogonSession ls, ServiceInitManager sim) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(SCRIPT_XML_FILE_PARAM, sim.getScriptXmlFile());

        ActionRunner.run(new ScriptInstallationAction(), context);
    }

    /**
     * Runs the Entity Customization Tool.
     *
     * @param ls user logon session
     */
    public static void runCustomTool(LogonSession ls, ServiceInitManager sim) {
        ActionContext context = new ActionContext(ls);
        context.addParameter(CUSTOM_XML_DIR_PARAM, sim.getCustomXmlDir());
        context.addParameter(I18N_XML_DIR_PARAM, sim.getI18nXmlDir());

        ActionRunner.run(new CustomInstallationAction(), context);
    }

    /**
     * Starts scheduler.
     *
     * @param returnLines count lines of log to return
     * @param waitTimeout wait timeout
     * @return scheduler log
     */
    public static String startScheduler(int returnLines,
                                        long waitTimeout) {

        ServiceInitManager sim = new ServiceInitManager();
        return runScheduler(sim.getSchedulerStartCmd(), returnLines,
                waitTimeout);
    }

    /**
     * Stops scheduler.
     *
     * @param returnLines count lines of log to return
     * @param waitTimeout wait timeout
     * @return scheduler log
     */
    public static String stopScheduler(int returnLines,
                                       long waitTimeout) {

        ServiceInitManager sim = new ServiceInitManager();
        return runScheduler(sim.getSchedulerStopCmd(), returnLines,
                waitTimeout);
    }

    /**
     * Gets status of scheduler.
     *
     * @param returnLines count lines of log to return
     * @param waitTimeout wait timeout
     * @return scheduler log
     */
    public static String statusScheduler(int returnLines,
                                         long waitTimeout) {

        ServiceInitManager sim = new ServiceInitManager();
        return runScheduler(sim.getSchedulerStatusCmd(), returnLines,
                waitTimeout);
    }

    // ----------------------------------------------------- private methods

    //
    // Constructor.
    //

    private ServiceStartupManager() {
    }

    //
    // Run scheduler
    //
    private static String runScheduler(String command,
                                       int returnLines,
                                       long waitTimeout) {

        SchedulerLogReader logReader = null;

        if(logger.getLogger().isInfoEnabled()) {
            logger.INFO("Run scheduler as: " + command);
            logger.INFO("		return lines:" + returnLines);
            logger.INFO("		wait timeout:" + waitTimeout);
        }

        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec(command);

            logger.DEBUG("Looks like scheduler run...trying to read log");

            BufferedReader in = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));

            if(returnLines > 0) {
                // Read log.
                logReader = new SchedulerLogReader(in, returnLines);
                logReader.start();
            }

            if(waitTimeout > 0) {
                // Wait.
                try {
                    if(logReader != null) {
                        logReader.join(waitTimeout);
                    } else {
                        Thread.sleep(waitTimeout);
                    }
                } catch (InterruptedException e) {
                }
            }

            logger.DEBUG("Scheduler run successfully");

        } catch (IOException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }

        return (logReader == null) ? null:logReader.out.toString();
    }

    // ----------------------------------------------------- Inner class

    /**
     * <p>Read scheduler log</p>
     *
     * @author [ALB] Baranov Andrey
     * @version $Revision: 1.1 $ $Date: 2006/04/18 12:04:16 $
     */
    private static class SchedulerLogReader
            extends Thread {

        protected StringBuffer out;
        private BufferedReader in;
        private int readLines;

        public SchedulerLogReader(BufferedReader in, int readLines) {
            this.out = new StringBuffer();
            this.in = in;
            this.readLines = readLines;
        }

        public void run() {
            int line = 0;
            String s;
            try {
                while((s = in.readLine()) != null && line < readLines) {
                    out.append(s).append("\n");
                    line++;
                }
                out.append("...");
            } catch (IOException ex) {
            }
        }

    }
}
