001package jmri.jmrix.openlcb.swing.lccpro;
002
003import java.awt.*;
004
005import java.beans.PropertyChangeEvent;
006import java.beans.PropertyChangeListener;
007import java.awt.event.WindowEvent;
008
009import java.io.File;
010import java.io.IOException;
011
012import javax.swing.*;
013
014import jmri.*;
015import jmri.jmrix.can.CanSystemConnectionMemo;
016import jmri.util.swing.JmriJOptionPane;
017
018import org.openlcb.*;
019import org.openlcb.cdi.impl.ConfigRepresentation;
020
021/**
022 * Do a backup of a specified node.
023 *
024 * Not truly an Action, though it might be some day
025 * @author Bob Jacobsen   (c) 2026
026 */
027
028
029class NodeBackupAction {
030
031    private ConfigRepresentation _cdi;
032    private String _name;
033    
034    static JFileChooser directoryChooser = new JFileChooser();
035    static final String PREFNAME = "backupDirectory";
036    
037    static {
038        directoryChooser.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY);
039        directoryChooser.setDialogTitle(Bundle.getMessage("ChooseADirectory"));
040        directoryChooser.setSelectedFile(new File("."));
041        
042        var prefsMgr = InstanceManager.getDefault(UserPreferencesManager.class);
043        var dirPref = prefsMgr.getProperty(NodeBackupAction.class.getName(), PREFNAME);
044        if (dirPref != null) {
045            directoryChooser.setSelectedFile(new File(dirPref.toString()));
046        }
047
048    }
049    
050    public static void showOpenDialog(Component here) {
051        var response = directoryChooser.showOpenDialog(here);
052        
053        if (response == JFileChooser.APPROVE_OPTION) {
054            String directory = directoryChooser.getSelectedFile().getAbsolutePath();
055            var prefsMgr = InstanceManager.getDefault(UserPreferencesManager.class);
056            prefsMgr.setProperty(NodeBackupAction.class.getName(), PREFNAME, directory);
057        }
058    }
059    
060    public void doBackup(MimicNodeStore.NodeMemo nodememo, CanSystemConnectionMemo memo, String name) {
061        var node = nodememo.getNodeID();
062        _name = name;
063        log.info("Backup {} '{}' ", node.toString(), _name);    
064        
065        var iface = memo.get(OlcbInterface.class);
066        
067        _cdi = iface.getConfigForNode(node);
068               
069        // always show the status
070        JmriJOptionPane.showMessageDialogNonModal(null,
071                Bundle.getMessage("MessageCdiLoad", _name, node),
072                Bundle.getMessage("TitleCdiLoad", name),
073                JmriJOptionPane.INFORMATION_MESSAGE,
074                null);
075
076        if (_cdi.getRoot() != null) {
077            // configuration cache present, store and
078            // cancel window after short delay
079            storeCdiData();
080            jmri.util.ThreadingUtil.runOnGUIDelayed(() -> {
081                closeStatusWindow();
082                }, 1000); 
083
084        } else {
085            // configuration cache present, wait for it
086            // to arrive
087            _cdi.addPropertyChangeListener(new CdiListener());
088        }
089    }
090    
091    // close the progress window and save the contents 
092    // when the CDI has been completely read
093    private class CdiListener implements PropertyChangeListener {
094        @Override
095        public void propertyChange(PropertyChangeEvent e) {
096            String propertyName = e.getPropertyName();
097            log.debug("CdiListener event = {}", propertyName);
098
099            if (propertyName.equals("UPDATE_CACHE_COMPLETE")) {
100                closeStatusWindow();
101                storeCdiData();
102            }
103        }
104    }
105    
106    protected void closeStatusWindow() {
107        Window[] windows = Window.getWindows();
108        for (Window window : windows) {
109            if (window instanceof JDialog) {
110                JDialog dialog = (JDialog) window;
111                if (Bundle.getMessage("TitleCdiLoad", _name).equals(dialog.getTitle())) {
112                    dialog.dispatchEvent(new WindowEvent(dialog, WindowEvent.WINDOW_CLOSING));
113                }
114            }
115        }
116    }
117    
118    protected void storeCdiData() {
119        log.debug("Load complete");
120        var filename = org.openlcb.cdi.swing.CdiPanel
121                        .fileNameGenerator.generateFileName(_cdi, _name);
122        String directory = directoryChooser.getSelectedFile().getAbsolutePath();
123        String storeName = directory+File.separator+filename;
124        log.info("Storing to file {}", storeName);
125        try {
126            org.openlcb.cdi.cmd.BackupConfig.writeConfigToFile(storeName, _cdi);
127        } catch (IOException e) {
128            log.error("Error writing file! ", e);
129        }
130        
131    }
132
133    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NodeBackupAction.class);
134}