001package jmri.jmrit.ctc.ctcserialdata;
002
003import java.util.Arrays;
004import java.util.ArrayList;
005import java.util.List;
006
007import jmri.jmrit.ctc.*;
008import jmri.jmrit.ctc.editor.code.CommonSubs;
009import jmri.jmrit.ctc.editor.gui.FrmTRL_Rules;
010import jmri.jmrit.ctc.topology.TopologyInfo;
011
012/**
013 * This describes one traffic locking rule.
014 * <p>
015 * The TRLSwitch sub-class contains switch, alignment and ID values.
016 * <p>
017 * The list of traffic locking rules for each OS section are in the
018 * _mTRL_LeftTrafficLockingRules and _mTRL_RightTrafficLockingRuless variable
019 * in {@link CodeButtonHandlerData}.
020 * @author Dave Sand Copyright (C) 2020
021 */
022public class TrafficLockingData {
023    public String _mUserRuleNumber;
024    public String _mRuleEnabled;
025    public String _mDestinationSignalOrComment;
026    public List<TRLSwitch> _mSwitchAlignments;              // Up to 5 entries
027    public List<NBHSensor> _mOccupancyExternalSensors;      // Up to 9 entries
028    public List<NBHSensor> _mOptionalExternalSensors;       // Up to 2 entries
029
030    public TrafficLockingData() {
031    }
032
033    /**
034     * Constructor to take a TopologyInfo entry and create a properly formed "this".
035     *
036     * @param ruleNumber    Rule # (just an integer, starting with 1)
037     * @param destinationSignalMast String representation of the destination signal mast so user can see on the form.
038     * @param topologyInfo  Source of data.
039     */
040    public TrafficLockingData(int ruleNumber, String destinationSignalMast, TopologyInfo topologyInfo) {
041//         Note:  The Topology process needs to updated.  It needs to create this class for each
042//         row and update the appropriate instance of CodeButtonHandleData.
043        _mUserRuleNumber = FrmTRL_Rules.getRuleNumberString(ruleNumber);
044        _mRuleEnabled = FrmTRL_Rules.getRuleEnabledString();
045        _mDestinationSignalOrComment = topologyInfo.getDestinationSignalMast();
046
047        _mSwitchAlignments = new ArrayList<>();
048        for (int i = 0; i < 5; i++) {
049            if (topologyInfo.getOSSectionText(i) != null) {
050                int intID;
051                try {
052                    intID = Integer.parseInt(topologyInfo.getUniqueID(i));
053                } catch (NumberFormatException ex) {
054                    log.warn("TrafficLockingData format exception: id = {}", topologyInfo.getUniqueID(i));
055                    intID = 0;
056                }
057               _mSwitchAlignments.add(new TRLSwitch(topologyInfo.getOSSectionText(i), topologyInfo.getNormalReversed(i), intID));
058            }
059        }
060
061        _mOccupancyExternalSensors = new ArrayList<>();
062        for (int i = 0; i < 9; i++) {
063            String sensorName = topologyInfo.getSensorDisplayName(i);
064            NBHSensor sensor = CommonSubs.getNBHSensor(sensorName, false);
065            if (sensor != null && sensor.valid()) {
066                _mOccupancyExternalSensors.add(sensor);
067            }
068        }
069
070        _mOptionalExternalSensors = new ArrayList<>();
071    }
072
073    /**
074     * Create a list of occupancy sensors with 9 entries. Unused entries will be set to a dummy NBHSensor.
075     * @return a list of occupancy sensors.
076     */
077    public ArrayList<NBHSensor> getOccupancySensors() {
078        NBHSensor dummy = new NBHSensor("TrafficLockingData", "", "", "", true);  // NOI18N
079        NBHSensor[] occupancyArray = new NBHSensor[9];
080        Arrays.fill(occupancyArray, dummy);
081        ArrayList<NBHSensor> occupancyList = new ArrayList<>(Arrays.asList(occupancyArray));
082        for (int index = 0; index < _mOccupancyExternalSensors.size(); index++) {
083            occupancyList.set(index, _mOccupancyExternalSensors.get(index));
084        }
085        return occupancyList;
086    }
087
088    /**
089     * Create a list of optional sensors with 2 entries. Unused entries will be set to a dummy NBHSensor.
090     * @return a list of optional sensors.
091     */
092    public ArrayList<NBHSensor> getOptionalSensors() {
093        NBHSensor dummy = new NBHSensor("TrafficLockingData", "", "", "", true);  // NOI18N
094        NBHSensor[] optionalArray = new NBHSensor[2];
095        Arrays.fill(optionalArray, dummy);
096        ArrayList<NBHSensor> optionalList = new ArrayList<>(Arrays.asList(optionalArray));
097        for (int index = 0; index < _mOptionalExternalSensors.size(); index++) {
098            optionalList.set(index, _mOptionalExternalSensors.get(index));
099        }
100        return optionalList;
101    }
102
103    /**
104     * Create a list of unique ids with 5 entries.  Unused entries are set to -1.
105     * @return a list of ids
106     */
107    public ArrayList<Integer> getUniqueIDs() {
108        Integer[] ids = new Integer[5];
109        Arrays.fill(ids, -1);
110        ArrayList<Integer> idList = new ArrayList<>(Arrays.asList(ids));
111        for (int index = 0; index < _mSwitchAlignments.size(); index++) {
112            idList.set(index, _mSwitchAlignments.get(index)._mUniqueID);
113        }
114        return idList;
115    }
116
117    /**
118     * Create a list of alignments with 5 entries.  Unused entries are to to Normal.
119     * @return a list of alignments
120     */
121    public ArrayList<String> getAlignments() {
122        String[] alignment = new String[5];
123        Arrays.fill(alignment, Bundle.getMessage("TLE_Normal"));    // NOI18N
124        ArrayList<String> alignmentList = new ArrayList<>(Arrays.asList(alignment));
125        for (int index = 0; index < _mSwitchAlignments.size(); index++) {
126            alignmentList.set(index, _mSwitchAlignments.get(index)._mSwitchAlignment);
127        }
128        return alignmentList;
129    }
130
131    @Override
132    public String toString() {
133        String formattedString = String.format("%s,%s,%s",
134                _mUserRuleNumber != null ? _mUserRuleNumber : "",
135                _mRuleEnabled != null ? _mRuleEnabled : "",
136                _mDestinationSignalOrComment != null ? _mDestinationSignalOrComment : "");
137        StringBuilder buildString = new StringBuilder(formattedString);
138        _mSwitchAlignments.forEach(tlrSw -> {
139            buildString.append(",");
140            buildString.append(tlrSw._mUserText);
141            buildString.append(",");
142            buildString.append(tlrSw._mSwitchAlignment);
143            buildString.append(",");
144            buildString.append(tlrSw._mUniqueID);
145        });
146        _mOccupancyExternalSensors.forEach(sw -> {
147            buildString.append(",");
148            buildString.append(sw.getHandleName());
149        });
150        _mOptionalExternalSensors.forEach(sw -> {
151            buildString.append(",");
152            buildString.append(sw.getHandleName());
153        });
154        return buildString.toString();
155    }
156
157    public static class TRLSwitch {
158        public String _mUserText;
159        public String _mSwitchAlignment;
160        public int _mUniqueID;
161
162        public TRLSwitch(String text, String alignment, int uniqueID) {
163            _mUserText = text;
164            _mSwitchAlignment = alignment;
165            _mUniqueID = uniqueID;
166        }
167    }
168    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrafficLockingData.class);
169}