001package jmri.jmrit.logix;
002
003import java.util.HashMap;
004import java.util.Map;
005import java.util.Map.Entry;
006
007import jmri.InstanceManager;
008import jmri.implementation.AbstractShutDownTask;
009import jmri.jmrit.roster.Roster;
010import jmri.jmrit.roster.RosterEntry;
011import jmri.jmrit.roster.RosterSpeedProfile;
012import jmri.util.ThreadingUtil;
013
014/**
015 *
016 * Allows user to decide if (and which) SpeedProfiles to write to the Roster at
017 * the end of a session. Locos running warrants have had their speeds measured
018 * and this new data may or may not be merged into any existing SpeedProfiles in
019 * the Roster.
020 *
021 * @author Pete cressman Copyright (C) 2017
022 */
023public class WarrantShutdownTask extends AbstractShutDownTask {
024
025    private HashMap<String, Boolean> _mergeCandidates;
026    private HashMap<String, RosterSpeedProfile> _mergeProfiles;
027    private Map<String, Map<Integer, Boolean>> _anomalies;
028    
029    /**
030     * Constructor specifies the warning message and action to take
031     *
032     * @param name the name of the task (used in logs)
033     */
034    public WarrantShutdownTask(String name) {
035        super(name);
036    }
037
038    /**
039     * {@inheritDoc}
040     */
041    @Override
042    public Boolean call() {
043        WarrantPreferences preferences = WarrantPreferences.getDefault();
044        switch (preferences.getShutdown()) {
045            case MERGE_ALL:
046                if (makeMergeCandidates()) {
047                    if (_anomalies != null && !_anomalies.isEmpty()) {
048                        makeMergeWindow();
049                    }
050                    setDoRun(true);
051                }
052                break;
053            case PROMPT:
054                if (makeMergeCandidates()) {
055                    makeMergeWindow();
056                    setDoRun(true);
057                }
058                break;
059            case NO_MERGE:
060                // do nothing
061                break;
062            default:
063                log.warn("No choice made for warrant shutdown");
064                break;
065        }
066        return true;
067    }
068
069    /**
070     * {@inheritDoc}
071     */
072    @Override
073    public void run() {
074        if (isDoRun()) {
075            merge();
076        }
077    }
078
079    private boolean makeMergeCandidates() {
080        WarrantManager manager = InstanceManager.getDefault(WarrantManager.class);
081        _mergeProfiles = manager.getMergeProfiles();
082        if (_mergeProfiles == null || _mergeProfiles.isEmpty()) {
083            return false;
084        }
085        _anomalies = new HashMap<>();
086        _mergeCandidates = new HashMap<>();
087        for (java.util.Map.Entry<String, RosterSpeedProfile> entry : _mergeProfiles.entrySet()) {
088            Map<Integer, Boolean> anomaly = MergePrompt.validateSpeedProfile(entry.getValue());
089            if (anomaly != null && !anomaly.isEmpty()) {
090                _anomalies.put(entry.getKey(), anomaly);
091            }
092            String rosterId = entry.getKey();
093            if (Roster.getDefault().getEntryForId(rosterId) != null) {
094                _mergeCandidates.put(rosterId, true);
095            }
096        }
097        return !_mergeCandidates.isEmpty();
098    }
099
100    private void makeMergeWindow() {
101        ThreadingUtil.runOnGUI( () -> new MergePrompt(Bundle.getMessage("MergeTitle"),
102            _mergeCandidates, _anomalies).setVisible(true));
103    }
104
105    private void merge() {
106        for (Entry<String, Boolean> entry : _mergeCandidates.entrySet()) {
107            if ( Boolean.TRUE.equals( entry.getValue()) ) {
108                String id = entry.getKey();
109                RosterEntry rosterEntry = Roster.getDefault().entryFromTitle(id);
110                if (rosterEntry != null) {
111                    rosterEntry.setSpeedProfile(_mergeProfiles.get(id));
112                    log.debug("Write SpeedProfile to Roster. id= {}", id);
113                } else {
114                    log.debug("Unable to Write SpeedProfile to Roster. No RosterEntry for {}", id);
115                }
116            } else {
117                log.debug("SpeedProfile not merged to Roster. id= {}", entry.getKey());
118            }
119        }
120        Roster.getDefault().writeRoster();
121    }
122
123    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WarrantShutdownTask.class);
124
125}