// Copyright (c) 2013 IBM Corporation and others. All rights reserved. 
// This program and the accompanying materials are made available under the 
// terms of the Eclipse Public License v1.0s which accompanies this distribution, 
// and is available at http://www.eclipse.org/legal/epl-v10.html

package org.eclipse.ptp.rm.ibm.lsf.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ptp.remote.core.IRemoteConnection;
import org.eclipse.ptp.remote.core.IRemoteProcess;
import org.eclipse.ptp.remote.core.IRemoteProcessBuilder;
import org.eclipse.ptp.remote.core.IRemoteServices;
import org.eclipse.ptp.rm.ibm.lsf.ui.widgets.Messages;

/**
 * This class implements invocation of LSF commands as a job running on a non-UI thread with the
 * ability for the user to cancel the job.
 */
public class LSFCommand implements IRunnableWithProgress {

    private String command[];
    private String commandDescription;
    private IRemoteConnection remoteConnection;
    protected Vector<String[]> commandResponse;
    protected String columnLabels[];
    public static final int OK = 0;
    public static final int COMMAND_ERROR = 3;
    public static final int CANCELED = 2;
    public static final int NO_DATA = 3;
    protected IRemoteProcess process;
    protected IStatus runStatus;

    /**
     * Constructor for creating a job to run a LSF command
     * 
     * @param name
     *            - Name of the job
     * @param connection
     *            The remote connection where the job will be run
     * @param cmd
     *            Array containing command name and command parameters
     */
    public LSFCommand(String name, IRemoteConnection connection, String cmd[]) {
        commandDescription = name;
        remoteConnection = connection;
        command = cmd;
        commandResponse = new Vector<String[]>();
    }

    /**
     * Run the LSF command specified when this object was created.
     * 
     * @param monitor
     *            - Progress monitor used to monitor and control job execution
     */
    @Override
    public void run(IProgressMonitor monitor) {
        monitor.beginTask(commandDescription, IProgressMonitor.UNKNOWN);
        runStatus = runCommand(monitor);
        if (runStatus.isOK() && (process.exitValue() == 0)) {
            runStatus = getCommandOutput(monitor);
        }
        monitor.done();
    }

    protected IStatus runCommand(IProgressMonitor monitor) {
        IRemoteServices remoteServices;
        IRemoteProcessBuilder processBuilder;

        remoteServices = remoteConnection.getRemoteServices();
        processBuilder = remoteServices.getProcessBuilder(remoteConnection, command);
        process = null;
        try {
            process = processBuilder.start();
            try {
                for (;;) {
                    if (process.isCompleted()) {
                        break;
                    }
                    if (monitor.isCanceled()) {
                        process.destroy();
                        return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
                    }
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                // Do nothing
            }
        } catch (IOException e) {
            return new Status(IStatus.ERROR, Activator.PLUGIN_ID, COMMAND_ERROR, Messages.LSFCommandFailed, e);
        }
        return new Status(IStatus.OK, Activator.PLUGIN_ID, OK, Messages.OkMessage, null);
    }

    protected IStatus getCommandOutput(IProgressMonitor monitor) {
        BufferedReader reader;
        String columnData[];
        String data;
        boolean headerLine;

        /*
         * Read stderr and check for "No application profiles found."
         * as the first line of output. Subsequent lines are ignored.
         */
        try {
            reader = new BufferedReader(new InputStreamReader(
                    process.getErrorStream()));
            data = reader.readLine();
            headerLine = true;
            while (data != null) {
                if (headerLine) {
                    if (data.equals("No application profiles found.")) { //$NON-NLS-1$
                        reader.close();
                        return new Status(IStatus.INFO, Activator.PLUGIN_ID, NO_DATA, Messages.NoProfileMessage, null);
                    }
                    headerLine = false;
                }
                data = reader.readLine();
                if (monitor.isCanceled()) {
                    reader.close();
                    return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
                }
            }
            reader.close();
            /*
             * Read stdout and tokenize each line of data into an array of
             * blank-delimited strings. The first line of output is the
             * column headings. Subsequent lines are reservation data.
             */
            reader = new BufferedReader(new InputStreamReader(
                    process.getInputStream()));
            data = reader.readLine();
            headerLine = true;
            commandResponse.clear();
            while (data != null) {
                if (headerLine) {
                    if (data.equals("No reservation found")) { //$NON-NLS-1$
                        reader.close();
                        return new Status(IStatus.INFO, Activator.PLUGIN_ID, NO_DATA, Messages.NoReservationMessage, null);
                    } else {
                        columnLabels = data.split(" +"); //$NON-NLS-1$
                        headerLine = false;
                    }
                } else {
                    data = data.replaceAll(" +/ +", "/"); //$NON-NLS-1$ //$NON-NLS-2$
                    columnData = data.split(" +"); //$NON-NLS-1$
                    commandResponse.add(columnData);
                }
                data = reader.readLine();
                if (monitor.isCanceled()) {
                    reader.close();
                    return new Status(IStatus.CANCEL, Activator.PLUGIN_ID, CANCELED, Messages.CommandCancelMessage, null);
                }
            }
            reader.close();
        } catch (IOException e) {
            return new Status(IStatus.ERROR, Activator.PLUGIN_ID, COMMAND_ERROR, "Error reading command output", e);
        }
        return new Status(IStatus.OK, Activator.PLUGIN_ID, OK, Messages.OkMessage, null);
    }

    /**
     * Get the command response
     * 
     * @return Command response
     */
    public Vector<String[]> getCommandResponse() {
        return commandResponse;
    }

    /**
     * Get the column headings. Column headings are the first line of the command response data
     * where each column has a blank-delimited column heading
     * 
     * @return Column heading data
     */
    public String[] getColumnLabels() {
        return columnLabels;
    }

    public IStatus getRunStatus() {
        return runStatus;
    }
}
