/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate;

import java.awt.Dialog;
import java.awt.Component;
import java.awt.Dimension;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import javax.swing.event.EventListenerList;
import javax.swing.JDialog;
import java.io.File;
import javax.swing.JPanel;
import org.openide.ErrorManager;

import org.openide.WizardDescriptor;
import org.openide.NotifyDescriptor;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.awt.StatusDisplayer;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

/** Implements the behavior of AutoUpdate wizard
 *
 * @author  Petr Hrebejk
 * @version 
 */
public class Wizard extends Object implements WizardDescriptor.Iterator {

    /** Structure of the updates */
    private Updates updates;

    /** pairs AutoupdateType, Updates */
    private static HashMap allUpdates = new HashMap();
    
    private static int errorType = Updates.NO_ERROR;
    private static String errorMessage;
    
    private static RequestProcessor processor;
    
    /** Panels of the wizard */
    private WizardPanel[][] panels = new WizardPanel[][] {
                                         { new StartPanel(),
                                           new PropPanel(),
                                           null,
                                           new ConfigPanel(),
                                           new DownloadPanel(),
                                           new LastPanel()
                                         },

                                         { null,
                                           null,
                                           new SelectPanel(),
                                           null,
                                           null,
                                           null
                                         }
                                     };

    /** Current panel */
    private int current = 0;

    private int modulesOK = 0;

    private boolean canceled = false;

    /** Which type of wizard should run */
    private int wizardType = 0;

    /** The wizard descriptor */
    private WizardDescriptor wizardDescriptor;    
    
    private List auTypesWithCust = new ArrayList();
    
    private HashMap installNow = new HashMap();

    /** The dialog */
    static Dialog dialog;
    
    Wizard() {
        this( null );
    }

    /** Creates the wizard */
    Wizard( HashMap allUpd ) {
        this( allUpd, 0 );
    }
    
    private PropertyChangeListener updater_listener = 
            new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent event) {
                    if (event.getPropertyName().equals("FINISHED")) {
                        Wizard.this.updaterFinished();
                    }
                }
            };
    
    private void updaterFinished() {
        if ( SafeModule.write( installNow ) ) {
            final String message = getBundle( "MSG_Install_Finished" ); // NOI18N
            StatusDisplayer.getDefault().setStatusText(message);
            
            // 64096: remove a lost Waiting ... message
            RequestProcessor.getDefault ().post (new Runnable () {
                public void run () {
                    if (message.equals (StatusDisplayer.getDefault ().getStatusText ())) {
                        StatusDisplayer.getDefault ().setStatusText (""); // NOI18N
                    }
                }
            }, 5000);
        }   
        else
            finishDialog( true );
    }
    
    private void finishDialog(boolean all) {
        if ( FinishDialog.showDialog() ) {
            Collection modules = getAllModules();
            Iterator it = modules.iterator();
            while( it.hasNext() ) {
                ModuleUpdate mu = (ModuleUpdate)it.next();

                if ( mu.isInstallApproved() && mu.isDownloadOK() && ( all || !mu.isSafeToInstall() ) ) {
                    if (!mu.isSafeToInstall () && mu.isToInstallDir ()) {
                        if ( !Downloader.tryMove( mu ) ) {
                            try {
                                mu.setToInstallDir( false );
                            } catch (IllegalArgumentException iae) {
                                ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, iae);
                            }
                        }
                    }
                    
                    PreparedModules.getPrepared().addModule( mu );
                }
            }
            if ( FinishDialog.isRestart() ) {
                PreparedModules.getPrepared().delete();
                Autoupdater.restart();
            }
            else {
                PreparedModules.getPrepared().write();
            }
        }
        else {
            Downloader.deleteDownload();
        }
    }
    
    /** Creates the wizard */
    Wizard( HashMap allUpd, int wizardType ) {
        
        this.wizardType = wizardType;

        // Create the wizard

        PropertyChangeListener listener = new PropertyChangeListener() {
                                              public void propertyChange(PropertyChangeEvent event) {
                                                  if (event.getPropertyName().equals(DialogDescriptor.PROP_VALUE)) {
                                                      Object option = event.getNewValue();

                                                      if (option == WizardDescriptor.FINISH_OPTION ||
                                                              option == NotifyDescriptor.CANCEL_OPTION ||
                                                              option == NotifyDescriptor.CLOSED_OPTION) {
                                                          if ( option != WizardDescriptor.FINISH_OPTION ) {
                                                              canceled = true;
                                                              Downloader.deleteDownload();
                                                          }
                                                          getCurrent().end( true );
                                                          dialog.setVisible(false);
                                                          Autoupdater.Support.deleteTempDir();
                                                          Autoupdater.setRunning( false );
                                                          dialog.dispose();
                                                          allUpdates.clear();
                                                          dialog = null;
                                                      }
                                                  }
                                              }
                                          };

        Updates.reset();
        if ( allUpd != null ) {
            int ist = 3;
            
            allUpdates = allUpd;
            current = ist;
            if ( wizardType == 0 )
                panels[0][ist].start( true );
        }

        wizardDescriptor = new WizardDescriptor( this );//, new Object() );
        wizardDescriptor.setModal( false );
        wizardDescriptor.setTitle(getBundle( "CTL_Wizard"));
        wizardDescriptor.setTitleFormat (new java.text.MessageFormat (" {0}"));  // NOI18N
        wizardDescriptor.setAdditionalOptions (new Object[] { });
        wizardDescriptor.addPropertyChangeListener(listener);
        wizardDescriptor.putProperty ("WizardPanel_helpDisplayed", Boolean.FALSE);
        wizardDescriptor.setOptions (new Object[] {
                                         WizardDescriptor.PREVIOUS_OPTION,
                                         WizardDescriptor.NEXT_OPTION,
                                         WizardDescriptor.FINISH_OPTION,
                                         NotifyDescriptor.CANCEL_OPTION } );
    }
    
    /** Runs the wizard */
    static void go( HashMap allUpd ) {
        go( allUpd, 0 );
    }
     
    /** Runs the wizard */
    static Wizard go( HashMap allUpd, int wizardType ) {
        
        if ( !tryToRun() ) {
            // UC wizard already running dialog
            DialogDisplayer.getDefault().notify( 
                    new NotifyDescriptor.Message(
                        getBundle( "MSG_WizardRunning"),
                        NotifyDescriptor.WARNING_MESSAGE
                    )
                );
            return null;
        }
        else {
            Wizard wiz = new Wizard ( allUpd, wizardType );
            wiz.startDialog();
            return wiz;
        }
        
    }
    
    void refreshUpdatePanel() {
        if ( current == 3 )
            panels[0][current].start( true );
    }
    
    /** Runs the wizard */
    public static void go() {
        
        if ( !tryToRun() ) {
            if ( dialog != null ) {
                dialog.requestFocus();
                // because of JDK 1.4
                if ( dialog instanceof JDialog )
                    ((JDialog)dialog).getRootPane().requestDefaultFocus();
            }
        }
        else {
            Wizard wiz = new Wizard ();
            wiz.startDialog();
        }
        
    }
    
    private static synchronized boolean tryToRun() {
        if ( !Autoupdater.isRunning() ) {
            Autoupdater.setRunning( true );
            return true;
        }
        return false;
    }

    private void startDialog() {
        dialog = DialogDisplayer.getDefault().createDialog( wizardDescriptor );

        canceled = false;

        dialog.setVisible (true);
        dialog.toFront();
    }
    
    // Implementation of Iterator --------------------------------------------------------

    public String name() {
        return getCurrent().getName();
    }

    public WizardDescriptor.Panel current() {

        return getCurrent();
        /*
        return panels[ wizardType ][ current ] == null ?
          panels[ 0 ][ current ] : panels[ wizardType ][ current ];
        */
    }

    private WizardPanel getCurrent() {

        return panels[ wizardType ][ current ] == null ?
               panels[ 0 ][ current ] : panels[ wizardType ][ current ];
    }

    public boolean hasNext() {

        if ( current == 1 && getCurrent().nextPanelOffset() == -1 )
            return false;
        else
            return current < panels[wizardType].length - 1;
    }

    public boolean hasPrevious() {

        return current > 0;
    }

    public void nextPanel() {

        getCurrent().end( true );

        if ( current < 0 && wizardType == 0 )
            current = current + 2;
        else if ( current == 0 && wizardType == 1 )
            current = 2;        
        else if ( current == 0 && wizardType == 0 && auTypesWithCust.size() == 0 )
            current = 3;        
        else if ( current == 1 && wizardType == 0  && auTypesWithCust.size() == 0 )
            current = current + 2;
        else if ( current == 1 && wizardType == 0  && auTypesWithCust.size() > 0 )
            current = 1;
        else if ( current == 3 && getCurrent().nextPanelOffset() == 2 )
            current = 5;
        else
            current ++;

        getCurrent().start( true );

        //centerDialog();
    }

    public void previousPanel() {

        getCurrent().end( false );

        switch ( current ) {
        case 2:
            if ( wizardType == 1 )
                current = 0;
            else
                current--;
            break;
        case 3:
            if ( wizardType == 0 )
                current = 0;
            else
                current--;
            break;
        case 5:
            current = 3;
            break;
        default:
            current --;
            break;
        }

        getCurrent().start( false );
        //centerDialog();
    }

    public synchronized void addChangeListener(javax.swing.event.ChangeListener listener) {}
    public synchronized void removeChangeListener(javax.swing.event.ChangeListener listener) {}

    static HashMap getAllUpdates() {
        return allUpdates;
    }
    
    static void setAllUpdates(HashMap allUpd) {
        allUpdates = allUpd;
    }
    
    static Collection getAllModules() {
        Set ret = new HashSet();
        Iterator it = getAllUpdates().values().iterator();
        while (it.hasNext()) {
            Object modules = ((Updates)it.next()).getModules();
            if (modules != null) {
                ret.addAll((Collection)modules);
            }
        }
        return ret;
    }
    
    static RequestProcessor getRequestProcessor() {
        if ( processor == null )
            processor = new RequestProcessor();
        return processor;
    }
    
    private static String getBundle( String key ) {
        return NbBundle.getMessage( Wizard.class, key );
    }
    
    // Inner classes ----------------------------------------------------------------------

    static interface Validator {

        // Called from component when the next button should be enabled or disbled
        public void setValid( boolean valid );

    }

    abstract class WizardPanel implements WizardDescriptor.Panel, Validator {

        protected Dimension WIZARD_SIZE = new Dimension( 550, 400 );

        protected boolean valid = true;

        /** Utility field used by event firing mechanism. */
        private EventListenerList listenerList = new EventListenerList();

        void start( boolean forward ) {}

        void end( boolean forward ) { }

        /** Called to get offset of the new panel */
        int nextPanelOffset() {
            return 1;
        }

        abstract String getName();

        // Implementation of Validator

        public void setValid(boolean valid) {
            this.valid = valid;
            fireChangeListenerStateChanged( this );
        }

        // Implementation of WizardDescriptor.Panel

        public boolean isValid() {
            return valid;
        }

        public HelpCtx getHelp() {
            return null;
        }

        public abstract Component getComponent();

        public void readSettings( Object settings ) {}

        public void storeSettings( Object settings ) {}

        /** Registers ChangeListener to receive events.
         *@param listener The listener to register.
         */
        public synchronized void addChangeListener(javax.swing.event.ChangeListener listener) {
            listenerList.add (javax.swing.event.ChangeListener.class, listener);
        }

        /** Removes ChangeListener from the list of listeners.
         *@param listener The listener to remove.
         */
        public synchronized void removeChangeListener(javax.swing.event.ChangeListener listener) {
            listenerList.remove (javax.swing.event.ChangeListener.class, listener);
        }

        /** Notifies all registered listeners about the event.
         *
         *@param param1 Parameter #1 of the <CODE>ChangeEvent<CODE> constructor.
         */
        protected void fireChangeListenerStateChanged(java.lang.Object param1) {
            javax.swing.event.ChangeEvent e = null;
            Object[] listeners = listenerList.getListenerList ();
            for (int i = listeners.length-2; i>=0; i-=2) {
                if (listeners[i]==javax.swing.event.ChangeListener.class) {
                    if (e == null)
                        e = new javax.swing.event.ChangeEvent (param1);
                    ((javax.swing.event.ChangeListener)listeners[i+1]).stateChanged (e);
                }
            }
        }
    }

    class StartPanel extends WizardPanel {

        FirstPanel firstPanel;
        
        String getName() {
            return getBundle( "CTL_StartPanel");
        }

        /** In this case set valid is used for setting the right wizard type
        */
        public void setValid( boolean valid ) {
            wizardType = ((FirstPanel)getComponent ()).getWizardType();                        
        }

        public Component getComponent() {
            if (firstPanel == null) {
                firstPanel = new FirstPanel( this ) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return firstPanel;
        }
        
        public HelpCtx getHelp() {
            return null;
            //return new HelpCtx( org.netbeans.modules.autoupdate.FirstPanel.class );
        }

        void end( boolean forward ) {
            allUpdates.clear();
            auTypesWithCust.clear();
            resetErrorStore ();
            
            Downloader.deleteDownload();
            if ( wizardType == 0 ) {                
                if ( !canceled ) {
                    int sum = 0;
                    Enumeration en = AutoupdateType.autoupdateTypes();
                    // check all autoupdates in sequence
                    while (en.hasMoreElements()) {
                        AutoupdateType at = (AutoupdateType)en.nextElement();
                        boolean hasCust = false;
                        if (at.isEnabled()) {
                            try {
                                if (java.beans.Introspector.getBeanInfo(at.getClass())
                                        .getBeanDescriptor().getCustomizerClass() != null) {
                                    auTypesWithCust.add(at);
                                    sum ++;
                                    hasCust = true;
                                }
                            } catch (Exception e) {
                            }
                            if (! hasCust) {
                                updates = at.connectForUpdates();
                                updates.checkUpdates( this, at );
                                int res = checkConnect(updates, at);
                                if ( res == ConnectingDialog.OK ) {
                                    sum ++;
                                    allUpdates.put(at, updates);
                                } else if ( res == ConnectingDialog.CANCEL ) {
                                    current = -2;
                                    return;
                                }
                            }
                        }
                    }
                    if (sum == 0){
                        if (isErrorStored ()) {
                            ConnectingErrorDialog.showDialog(errorType, errorMessage);
                        } else {
                            ConnectingErrorDialog.showDialog(Updates.NO_SERVER_ERROR, null);
                        }
                        current = -2;
                        return;
                    }
                }
            }
        }
    }
    
    class PropPanel extends WizardPanel {

        LoginPanel lPanel;
        AutoupdateType currentAT;
        JPanel custPanel;
        
        HelpCtx userHelp = null;
        
        String getName() {
            return getBundle( "CTL_StartPanel");
        }

        /** In this case set valid is used for setting the right wizard type
        */
        public void setValid( boolean valid ) {                                    
        }

        public Component getComponent() {
            if (lPanel == null) {
                lPanel = new LoginPanel( this ) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return lPanel;
        }

        public HelpCtx getHelp() {
            if ( userHelp != null )
                return userHelp;
            else
                return null;
                //return new HelpCtx( org.netbeans.modules.autoupdate.LoginPanel.class );
        }
        
        void start( boolean forward ) {
            if ( custPanel != null )
                return;
            currentAT = (AutoupdateType)auTypesWithCust.get(0);
            userHelp = null;
            try {
                custPanel = (javax.swing.JPanel)(java.beans.Introspector.getBeanInfo(currentAT.getClass())
                    .getBeanDescriptor().getCustomizerClass().newInstance());
                ((LoginPanel)getComponent ()).setCustomizer(custPanel, currentAT);
                userHelp = (HelpCtx) custPanel.getClientProperty( "Autoupdate_HelpID" ); // NOI18N
            } catch (Exception e) {
            }
        }
        
        void end( boolean forward ) {
            //System.out.println("Ending start" ); // NOI18N
            if ( wizardType == 0 ) {
                Downloader.deleteDownload();
                if ( !canceled && forward ) {
                    updates = currentAT.connectForUpdates();
                    updates.checkUpdates( this, currentAT );
                    int res = checkConnect(updates, currentAT);
                    if ( res == ConnectingDialog.OK )
                        allUpdates.put(currentAT, updates);
                    else if ( res == ConnectingDialog.CANCEL ) {
                        if ( updates.isError() ) {
                            current = -1;
                            return;
                        }
                        else
                            current = -2;
                    }
                }
                auTypesWithCust.remove(0);
                custPanel = null;
            }
        }       

    }
    
    static void resetErrorStore () {
        errorMessage = null;
        errorType = Updates.NO_ERROR;
    }
    
    static private void storeError (int type, String msg) {
        if (type == Updates.NO_ERROR) {
            throw new IllegalArgumentException ("Type Updates.NO_ERROR is not error.");
        }
        errorType = type;
        errorMessage = msg;
    }
    
    static boolean isErrorStored () {
        return errorType != Updates.NO_ERROR;
    }
    
    static int getStoredErrorType () {
        return errorType;
    }
    
    static String getStoredErrorMessage () {
        return errorMessage;
    }
    
    static int checkConnect(Updates updates, AutoupdateType at) {                                       
        if (ConnectingDialog.isCanceled()) {
            return ConnectingDialog.CANCEL;
        }
        else if (ConnectingDialog.isSkipped()) {
            return ConnectingDialog.SKIP;
        }        
        else if ( updates.isError() ) {
            storeError (updates.getError(), updates.getErrorMessage ());
            return ConnectingDialog.SKIP;
        }
        else if ( updates.getModules() != null && updates.getModules().size() > 0 )
            Notification.performNotification( updates, at );
        return ConnectingDialog.OK;
    }

    class ConfigPanel extends WizardPanel {

        private UpdatePanel updatePanel = null;

        public void setValid( boolean valid ) {
            super.setValid( valid );
            if ( dialog != null )
                dialog.repaint( );
        }

        String getName() {
            return getBundle( "CTL_ConfigPanel");
        }

        public Component getComponent() {
            if (updatePanel == null) {
                updatePanel = new UpdatePanel( this ) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return updatePanel;
        }

        public HelpCtx getHelp() {
            return null;
            //return new HelpCtx( org.netbeans.modules.autoupdate.UpdatePanel.class );
        }
        
        public boolean isValid() {
            return valid;
        }

        void start( boolean forward ) {
            valid = false;
            if ( forward ) {
                PreparedModules.readPrepared();
                if (wizardType == 0) {
                    Iterator atypes = allUpdates.keySet().iterator();
                    while ( atypes.hasNext() ) {
                        AutoupdateType at = (AutoupdateType)atypes.next();
                        Updates upd = (Updates)allUpdates.get( at );
                        at.setLastTimeStamp( upd.getTimeStamp() );
                    }
                }
            }
            ((UpdatePanel)getComponent ()).setUpdates( wizardType );            
        }

        void end( boolean forward ) {
            if ( forward ) {
                ((UpdatePanel)getComponent ()).markSelectedModules();
                if ( !canceled )
                    if ( !((UpdatePanel)getComponent ()).checkLicencies() )
                        current--;
            }
            ((UpdatePanel)getComponent ()).removeListeners();
        }

        int nextPanelOffset() {
            if ( ((UpdatePanel)getComponent ()).modulesToDownload() == 0 )
                return 2;
            else
                return 1;
        }
        
        void setUpdates(HashMap allUpd) {
            allUpdates.clear();
            allUpdates = allUpd;
        }

    }

    class DownloadPanel extends WizardPanel {

        private Downloader downloader;
        private SignVerifier signVerifier;

        private DownloadProgressPanel progressPanel = null;

        private boolean isDownloadFinished;

//        public void setValid( boolean valid ) {
//
//            // First call to setValid means the signVerifier is ready to run
//            if ( !isDownloadFinished && valid) {
//                isDownloadFinished  = true;
//            }
//            // This is the real end
//            else {
//                super.setValid( valid );
//                ((ProgressDialog)getComponent ())
//                ((DownloadProgressPanel)getComponent ()).setEnableStop(false);
//            }
//        }
//
        String getName() {
            return getBundle( wizardType == 0 ? "CTL_DownloadPanel" : "CTL_CopyPanel" ); // NOI18N
        }

        public Component getComponent() {
            if (progressPanel == null) {
                progressPanel =  new DownloadProgressPanel(this) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return ( Component )progressPanel;
        }
        
        public HelpCtx getHelp() {
            return null;
            //return new HelpCtx( org.netbeans.modules.autoupdate.DownloadProgressPanel.class );
        }

        void start( boolean forward ) {
            valid = false;
            isDownloadFinished = false;
            // needs to re-initialize DownloadProgressPanel when Back->Next - problem with the progress components
            progressPanel = null;
            downloader = new Downloader( ((DownloadProgressPanel)getComponent ()), this, wizardType == 0 );
            downloader.doDownload();
            // Sign verifier is called in setValid function
        }

        void end( boolean forward ) {
            if ( !valid ) {
                if ( !isDownloadFinished ) {
                    downloader.cancelDownload();
                } else {
                    if (signVerifier != null) {
                        signVerifier.cancelVerify( canceled );
                    }
                }
            }
        }

    }

    class LastPanel extends WizardPanel {

        ResultsPanel resultsPanel;

        String getName() {
            return getBundle( wizardType == 0 ? "CTL_ResultsPanel" : "CTL_ResultsPanel_1"); // NOI18N
        }

        public Component getComponent() {
            if (resultsPanel == null) {
                resultsPanel = new ResultsPanel( this ) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return resultsPanel;
        }

        public HelpCtx getHelp() {
            return null;
            //return new HelpCtx( org.netbeans.modules.autoupdate.ResultsPanel.class );
        }
        
        void start( boolean forward ) {
            modulesOK = ((ResultsPanel)getComponent ()).generateResults();            
        }
        
        void end( boolean forward ) {
            if ( wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION
                && modulesOK > 0 ) {

                Collection modules = getAllModules();
                Iterator it = modules.iterator();
                installNow = new HashMap();
                int otherCount = 0;
                while( it.hasNext() ) {
                    ModuleUpdate mu = (ModuleUpdate)it.next();

                    if ( mu.isDownloadOK() && Downloader.getNBM( mu ).exists() ) {
                        if ( !mu.isInstallApproved() ) {
                            Downloader.getNBM( mu ).delete();
                            Downloader.getNBM( mu ).deleteOnExit();
                        } else {
                            if ( mu.isSafeToInstall() ) {
                                if ( mu.isToInstallDir() )
                                    if ( !Downloader.tryMove( mu ) ) {
                                        try {
                                            mu.setToInstallDir( false );
                                        } catch (IllegalArgumentException iae) {
                                            ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, iae);
                                        }
                                    }
                                installNow.put( mu, Downloader.getMovedNBM( mu ) );
                            }
                            else {
                                otherCount++;
                            }
                        }
                    }
                }
                
                Autoupdater.Support.deleteTempDir();
                if ( installNow.size() > 0 && otherCount == 0 ) {
                    File[] filesInstallNow = new File[]{};        
                    filesInstallNow = (File[])installNow.values().toArray(filesInstallNow);
                    org.netbeans.updater.UpdaterFrame.runFromIDE (filesInstallNow, updater_listener, NbBundle.getBranding ());
                }
                else if ( otherCount > 0 ) {
                    finishDialog( false );
                }
                else {
                    DialogDisplayer.getDefault().notify( 
                        new NotifyDescriptor.Message(
                            getBundle( "MSG_WizardNoNbms"),
                            NotifyDescriptor.WARNING_MESSAGE
                        )
                    );
                }
            }

            Autoupdater.setRunning( false );
        }
    }

    // Panels for installing manualy downloaded modules ---------

    class SelectPanel extends WizardPanel {

        private SelectModulesPanel selectModulesPanel = null;

        String getName() {
            return getBundle( "CTL_SelectModulesPanel");
        }

        public Component getComponent() {
            if (selectModulesPanel == null) {
                selectModulesPanel = new SelectModulesPanel( this ) {
                    public Dimension getPreferredSize() {
                        return WIZARD_SIZE;
                    }
                };
            }
            return selectModulesPanel;
        }
        
        public HelpCtx getHelp() {
            return null;
            //return new HelpCtx( org.netbeans.modules.autoupdate.SelectModulesPanel.class );
        }

        void start( boolean forward ) {
            valid = false;
            if ( forward )
                ((SelectModulesPanel)getComponent ()).reset();
            else
                setValid( true );
        }

        void end( boolean forward ) {

            if ( forward && !canceled ) {
                updates = new XMLUpdates( ((SelectModulesPanel)getComponent ()).getFiles() );
                ((XMLUpdates)updates).checkDownloadedModules();
                allUpdates.put(this, updates);
            }
        }

    }

}
