/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * END COPYRIGHT BLOCK **/
package com.netscape.management.admserv.panel;

import java.lang.reflect.Method;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.net.*;
import com.netscape.management.client.util.*;
import com.netscape.management.client.console.ConsoleInfo;
import com.netscape.management.admserv.config.*;
import com.netscape.management.admserv.panel.IRestartControl;
import com.netscape.management.nmclf.SuiLookAndFeel;
import javax.swing.border.EmptyBorder;

/**
  *
  * @version 0.1 11/28/97
  * @author miodrag@netscape.com
  */
public class AdminOperation {
    static ResourceSet _resource;
    static String _i18nStatus, _i18nFailureStatus, _i18nWarningStatus,
    _i18nCanNotConnect, _i18nServerShutdown;
    static String _i18nOperationDone, _i18nOperationFailed;

    static {
        _resource = new ResourceSet("com.netscape.management.admserv.panel.panel");
        _i18nStatus = _resource.getString("adminop","Status");
        _i18nFailureStatus = _resource.getString("adminop","FailureStatus");
        _i18nWarningStatus = _resource.getString("adminop","WarningStatus");
        _i18nCanNotConnect = _resource.getString("adminop","CanNotConnect");
        _i18nServerShutdown = _resource.getString("adminop","ServerShutdown");
        _i18nOperationDone = _resource.getString("adminop","OperationDone");
        _i18nOperationFailed = _resource.getString("adminop","OperationFailed");
    }


    protected ConsoleInfo _consoleInfo;
    protected boolean _actionPerformed;
    protected Hashtable _resultData;
    protected int _resultStatus;
    protected String _taskURL;
    protected IAdminOperationListener _listener;

    protected ActionMonitorPanel _actionPanel;
    protected AdmTask _task;

    public AdminOperation(ConsoleInfo consoleInfo, String taskURL) {
        _consoleInfo = consoleInfo;
        _taskURL = taskURL;
    }

    public JPanel getPanel() {
        return _actionPanel;
    }

    public Hashtable getConsoleInfo() {
        return _consoleInfo;
    }

    /**
      * Close dialog if base config panel is running inside a dialog
     */
    public Dialog getDialog() {
        Component c = _actionPanel;
        Dialog dialog = null;
        while ((c = c.getParent()) != null) {
            if (c instanceof Dialog) {
                dialog = (Dialog) c;
                break;
            }
        }
        return dialog;
    }

    public Frame getFrame() {
        Component c = _actionPanel;
        Frame frame = null;
        while ((c = c.getParent()) != null) {
            if (c instanceof Frame) {
                frame = (Frame) c;
                break;
            }
        }
        return frame;
    }

    protected void closeDialog() {
        Window dialog = getDialog();

        if (dialog != null) {
            dialog.setVisible(false);
            dialog.dispose();
            ModalDialogUtil.sleep();
        }
    }


    protected void createActionPanel(boolean multilined) {
        _actionPanel = new ActionMonitorPanel(multilined);
        //_actionPanel.setBorder(new EmptyBorder(0, SuiLookAndFeel.HORIZ_WINDOW_INSET,
        //SuiLookAndFeel.VERT_WINDOW_INSET, SuiLookAndFeel.HORIZ_WINDOW_INSET));
    }


    /**
      * Monitor execution of the operatinal task
     */
    public void monitorOperation(String description) {
        monitorOperation(description, null);
    }


    public void monitorOperation(String description,
            IAdminOperationListener listener) {

        if (ActionMonitorPanel.getActiveInstance() != null) {
            _actionPanel = ActionMonitorPanel.getActiveInstance();
            _actionPanel.setStatusText(description);
            try {
                AdminOperation.this.performOperation(listener);
            } catch (RemoteRequestException e) {
                ConfigErrorDialog.showDialog(_actionPanel, e);
            }
            return;
        }

        if (_actionPanel == null) {
            createActionPanel(false);
        }


        // Granting UniversalThreadGroupAccess before creating thread groups
        //(as instructed by DT)

        Method m = Permissions.getEnablePrivilegeMethod();
        if (m != null) {
            Object[] args = new Object[1];
            args[0] = "UniversalThreadGroupAccess";

            try {
                m.invoke(null, args);
            } catch (Exception e) {
                Debug.println(
                        "AdminOperation:monitorOperation():unable to grant ThreadGroup privileges:" + e);
            }
        }

        final ThreadGroup tg = new ThreadGroup("LongActionTG");
        final String status = description;
        final IAdminOperationListener listenerObject = listener;
        Thread t = new Thread(tg, "LongAction") {
                    public void run() {
                        // Give dialog time to popup
                        //try { Thread.currentThread().sleep(200); } catch (Exception e) {}
                        boolean noError = true;
                        _actionPanel.monitorProgressStart(status, tg,
                                _stopAction);
                        try {
                            AdminOperation.this.performOperation(
                                    listenerObject);
                        } catch (RemoteRequestException e) {
                            ConfigErrorDialog.showDialog(_actionPanel, e);
                            noError = false;
                        }
                        finally { if (noError &&
                                _actionPanel.isMultilined()) {
                                _actionPanel.monitorProgressWaitForClose();
                                return;
                            }
                            _actionPanel.monitorProgressStop(
                                    _actionPerformed ? _i18nOperationDone :
                                    _i18nOperationFailed);
                            // Some time to read status
                            try {
                                Thread.currentThread().sleep(500);
                            } catch (Exception e) {}
                            closeDialog();
                        } }

                    ActionListener _stopAction = new ActionListener() {
                                public void actionPerformed(
                                        ActionEvent e) {
                                    closeDialog();
                                }
                            };

                };
        t.start();
    }

    public void performOperation(IAdminOperationListener listener)
            throws RemoteRequestException {
        try {
            performOperationalTask(_consoleInfo, _taskURL);
            if (listener != null) {
                listener.cgiRequestCompleted(_consoleInfo);
            }
        } catch (RemoteRequestException e) {
            throw e;
        }
    }


    protected void createTask(ConsoleInfo ci,
            String adminURL) throws RemoteRequestException {

        try {
            _task = new AdmTask(new URL(adminURL), ci.getAuthenticationDN(),
                    ci.getAuthenticationPassword());
        } catch (MalformedURLException e) {
            Debug.println(""+e);
            throw new RemoteRequestException(e);
        }
    }

    public void performOperationalTask(ConsoleInfo ci,
            String taskURL) throws RemoteRequestException {


        String adminURL = ci.getAdminURL() + taskURL;
        createTask(ci, adminURL);

        //_task.trace();
        _task.exec();

        _resultStatus = _task.getStatus();
        _resultData = _task.getResult();
        _actionPerformed = (_resultStatus == 0 || _resultStatus == 3);
        processAdmTaskStatus(adminURL);
    }

    public boolean isActionPerformed() {
        return _actionPerformed;
    }

    public int getResultStatus() {
        return _resultStatus;
    }

    public Hashtable getResultData() {
        return _resultData;
    }


    // Need this as static methods can not be overriden
    protected void processAdmTaskStatus(String url)
            throws RemoteRequestException {
        processAdmTaskStatus(url, _task, _consoleInfo);
    }

    public static void processAdmTaskStatus(String url, AdmTask task,
            ConsoleInfo ci) throws RemoteRequestException {

        int status = task.getStatus();

        if (status == 0 || status == 3) {
            return;
        }
        else if (status < 0) { // -1 if HTTP Exception received
            Debug.println("HTTP Exception status=" + status + " " +
                    task.getException());
            if (task.getException() != null && task.getException()
                    instanceof java.net.SocketException) {
                IRestartControl serverStatus =
                        (IRestartControl) ci.get(IRestartControl.ID);
                if (serverStatus != null) {
                    if (serverStatus.isServerShutdown()) {
                        throw new RemoteRequestException("",
                                _i18nServerShutdown);
                    }
                } else {
                    Debug.println("StopOperation: restart activator not in ConsoleInfo");
                }

                // Server is not shutdown, throw can not connect
                throw new RemoteRequestException(url,
                        _i18nCanNotConnect + " "+
                        task.getException().getMessage());

            }
            else if (task.getException() != null) {
                throw new RemoteRequestException(task.getException());
            } else {
                throw new RemoteRequestException(url, _i18nStatus + status);
            }
        }
        else { // (status > 0)  an error generated by the CGI script
            String type;
            if (status == 1)
                type = _i18nStatus + _i18nFailureStatus;
            else if (status == 2)
                type = _i18nStatus + _i18nWarningStatus;
            else
                type = _i18nStatus + " " + status;

            String msg = "";
            Hashtable result = task.getResult();
            if (result != null) {
                for (Enumeration e = result.elements();
                        e.hasMoreElements();) {
                    Object key = e.nextElement();
                    //msg=msg + key + "=" + result.get(key) + "\n";
                    msg = msg + key + "\n";
                }
            }
            Debug.println("CGI error " + type + "\n" + msg);
            throw new RemoteRequestException(url, type + "\n" + msg);
        }
    }
}
