001package jmri.jmrit.ctc.ctcserialdata;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.HashSet;
006
007import jmri.Turnout;
008
009/**
010 *
011 * @author Gregory J. Bedlek Copyright (C) 2018, 2019
012 */
013public class CTCSerialData {
014
015    private OtherData _mOtherData;
016    private ArrayList<CodeButtonHandlerData> _mCodeButtonHandlerDataArrayList;
017
018    /**
019     * "Return" value from function "getCTCTurnoutData":
020     */
021    public static class CTCTurnoutData {
022        public final String   _mOSSectionText;
023        public final int      _mUniqueID;
024        public CTCTurnoutData(String OSSectionText, int uniqueID) {
025            _mOSSectionText = OSSectionText;
026            _mUniqueID = uniqueID;
027        }
028    }
029
030    public CTCSerialData() {
031        _mOtherData = new OtherData();
032        _mCodeButtonHandlerDataArrayList = new ArrayList<>();
033    }
034
035    public OtherData getOtherData() {
036        return _mOtherData;
037    }
038
039    public int getUniqueNumber() {
040        return _mOtherData.getNextUniqueNumber();
041    }
042
043    public CodeButtonHandlerData getCodeButtonHandlerDataViaUniqueID(int uniqueID) {
044        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
045            if (codeButtonHandlerData._mUniqueID == uniqueID) {
046                return codeButtonHandlerData;
047            }
048        }
049        return null;    // In case it's not found.
050    }
051
052    public String getMyShortStringNoCommaViaUniqueID(int uniqueID) {
053        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
054            if (codeButtonHandlerData._mUniqueID == uniqueID) {
055                return codeButtonHandlerData.myShortStringNoComma();
056            }
057        }
058        return "UNKNOWN";    // In case it's not found.
059    }
060
061    public int getIndexOfUniqueID(int uniqueID) {
062        for (int index = 0; index < _mCodeButtonHandlerDataArrayList.size(); index++) {
063            if (_mCodeButtonHandlerDataArrayList.get(index)._mUniqueID == uniqueID) {
064                return index;    // That's it.
065            }
066        }
067        return -1;  // not found.
068    }
069
070    public void setOtherData(OtherData otherData) {
071        _mOtherData = otherData;
072    }
073
074    public ArrayList<CodeButtonHandlerData> getCodeButtonHandlerDataArrayList() {
075        return _mCodeButtonHandlerDataArrayList;
076    }
077
078    public void addCodeButtonHandlerData(CodeButtonHandlerData codeButtonHandlerData) {
079        _mCodeButtonHandlerDataArrayList.add(codeButtonHandlerData);
080    }
081
082    public void removeCodeButtonHandlerData(int index) {
083        _mCodeButtonHandlerDataArrayList.remove(index);
084    }
085
086    public CodeButtonHandlerData getCodeButtonHandlerData(int index) {
087        return _mCodeButtonHandlerDataArrayList.get(index);
088    }
089
090    public int getCodeButtonHandlerDataSize() {
091        return _mCodeButtonHandlerDataArrayList.size();
092    }
093
094    public void moveUp(int index) {
095        try {
096            Collections.swap(_mCodeButtonHandlerDataArrayList, index, index - 1);
097        } catch (IndexOutOfBoundsException e) {
098        }    // Do NOTHING in this case!  Technically should never happen, since buttons aren't enabled for such possibilities
099    }
100
101    public void moveDown(int index) {
102        try {
103            Collections.swap(_mCodeButtonHandlerDataArrayList, index, index + 1);
104        } catch (IndexOutOfBoundsException e) {
105        }    // Do NOTHING in this case!  Technically should never happen, since buttons aren't enabled for such possibilities
106    }
107
108    /**
109     * Change the identifying attributes with the exception of the uniqueID.  The potential
110     * primary changes are the switch and signal numbers.
111     * @param index The row being changed.
112     * @param newSwitchNumber The new switch number which is always odd.
113     * @param newSignalEtcNumber The new signal number which is always one more than the switch number.
114     * @param newGUIColumnNumber The location on the panel.  Used by the GUI export process.
115     * @param newGUIGeneratedAtLeastOnceAlready A flag to indicate whether the GUI export should include this column.
116     */
117    public void updateSwitchAndSignalEtcNumbersEverywhere(int index, int newSwitchNumber, int newSignalEtcNumber, int newGUIColumnNumber, boolean newGUIGeneratedAtLeastOnceAlready) {
118        CodeButtonHandlerData codeButtonHandlerData = _mCodeButtonHandlerDataArrayList.get(index);
119        codeButtonHandlerData._mSwitchNumber = newSwitchNumber;
120        codeButtonHandlerData._mSignalEtcNumber = newSignalEtcNumber;
121        codeButtonHandlerData._mGUIColumnNumber = newGUIColumnNumber;
122        codeButtonHandlerData._mGUIGeneratedAtLeastOnceAlready = newGUIGeneratedAtLeastOnceAlready;
123        int UniqueIDBeingModified = codeButtonHandlerData._mUniqueID;
124        String replacementString = codeButtonHandlerData.myShortStringNoComma();
125        for (CodeButtonHandlerData temp : _mCodeButtonHandlerDataArrayList) {
126            updateTrlUserText(temp._mTRL_LeftTrafficLockingRules, UniqueIDBeingModified, replacementString);
127            updateTrlUserText(temp._mTRL_RightTrafficLockingRules, UniqueIDBeingModified, replacementString);
128        }
129    }
130
131    /**
132     * Update the text description of entries in the traffic locking rules located in TrafficLockingData.
133     * Each alignment entry in each rule is checked for match on uniqueID.  If so, the text is replaced.
134     * @param rulesToFix An array of TrafficLockingData entries.  Each entry is a rule.
135     * @param uniqueIDBeingModified The uniqueID being checked.
136     * @param replacementString The new sw/sig string.
137     */
138    private void updateTrlUserText(ArrayList<TrafficLockingData> rulesToFix, int uniqueIDBeingModified, String replacementString) {
139        rulesToFix.forEach(rule -> {
140            rule._mSwitchAlignments.forEach(alignment -> {
141                if (uniqueIDBeingModified == alignment._mUniqueID) {
142                    alignment._mUserText = replacementString;
143                }
144            });
145        });
146    }
147
148    public void setCodeButtonHandlerData(int index, CodeButtonHandlerData codeButtonHandlerData) {
149        _mCodeButtonHandlerDataArrayList.set(index, codeButtonHandlerData);
150    }
151
152//  If none are found, return -1 (which we'll then increment by 2 to 1, which is a good "add" default starting point):
153    public int findHighestSwitchNumberUsedSoFar() {
154        int highestSwitchNumber = -1;
155        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
156            if (codeButtonHandlerData._mSwitchNumber > highestSwitchNumber) {
157                highestSwitchNumber = codeButtonHandlerData._mSwitchNumber;
158            }
159        }
160        return highestSwitchNumber;
161    }
162
163//  If none are found, return 0 (which we'll then increment by 1 to 1, which is a good "add" default starting point):
164    public int findHighestColumnNumberUsedSoFar() {
165        int highestColumnNumber = 0;
166        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
167            if (codeButtonHandlerData._mGUIColumnNumber > highestColumnNumber) {
168                highestColumnNumber = codeButtonHandlerData._mGUIColumnNumber;
169            }
170        }
171        return highestColumnNumber;
172    }
173
174    /**
175     * Routine to search our _mCodeButtonHandlerDataArrayList for the O.S. section
176     * that contains the passed turnout.
177     *
178     * @param turnout   The turnout to search for in our table.
179     * @return          CTCTurnoutData, else if turnout not found, null.
180     */
181    public CTCTurnoutData getCTCTurnoutData(Turnout turnout) {
182        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
183            if (codeButtonHandlerData._mSWDI_Enabled) { // Only if it has one:
184                if (codeButtonHandlerData._mSWDI_ExternalTurnout.getBean().equals(turnout)) { // Ah match, this is us:
185                    return new CTCTurnoutData(codeButtonHandlerData.myShortStringNoComma(), codeButtonHandlerData._mUniqueID);
186                }
187            }
188        }
189        return null;
190    }
191
192    /**
193     * This routine is used to support FrmTUL.java.  It generates a HashSet (which
194     * prevents duplicate strings) of all such locked turnouts, EXCLUDING the
195     * passed "excludedOne", since that one will be handled locally in the calling
196     * code.
197     *
198     * @param excludedOne The one to NOT include in the returned information.
199     * @return All locked turnouts NOT INCLUDING excludedOne.
200     */
201    public HashSet<String> getHashSetOfAllLockedTurnoutsExcludingPassedOne(CodeButtonHandlerData excludedOne) {
202        HashSet<String> lockedTurnouts = new HashSet<>();
203        for (CodeButtonHandlerData codeButtonHandlerData : _mCodeButtonHandlerDataArrayList) {
204            if (codeButtonHandlerData != excludedOne) { // Process this one:
205                if (codeButtonHandlerData._mTUL_ExternalTurnout.valid()) { lockedTurnouts.add(codeButtonHandlerData._mTUL_ExternalTurnout.getHandleName()); }
206                if (codeButtonHandlerData._mTUL_AdditionalExternalTurnout1.valid()) { lockedTurnouts.add(codeButtonHandlerData._mTUL_AdditionalExternalTurnout1.getHandleName()); }
207                if (codeButtonHandlerData._mTUL_AdditionalExternalTurnout2.valid()) { lockedTurnouts.add(codeButtonHandlerData._mTUL_AdditionalExternalTurnout2.getHandleName()); }
208                if (codeButtonHandlerData._mTUL_AdditionalExternalTurnout3.valid()) { lockedTurnouts.add(codeButtonHandlerData._mTUL_AdditionalExternalTurnout3.getHandleName()); }
209            }
210        }
211        return lockedTurnouts;
212    }
213
214}