001package jmri.jmrit.operations.trains.csv;
002
003import java.io.IOException;
004import java.util.List;
005
006import org.apache.commons.csv.CSVPrinter;
007
008import jmri.InstanceManager;
009import jmri.jmrit.operations.locations.Location;
010import jmri.jmrit.operations.locations.Track;
011import jmri.jmrit.operations.rollingstock.cars.Car;
012import jmri.jmrit.operations.rollingstock.cars.CarManager;
013import jmri.jmrit.operations.rollingstock.engines.Engine;
014import jmri.jmrit.operations.routes.RouteLocation;
015import jmri.jmrit.operations.setup.Setup;
016import jmri.jmrit.operations.trains.Train;
017import jmri.jmrit.operations.trains.trainbuilder.TrainCommon;
018import jmri.util.FileUtil;
019
020/**
021 * Contains the csv operators for manifests and switch lists
022 *
023 * @author Daniel Boudreau Copyright (C) 2011, 2013, 2015, 2022, 2026
024 */
025public class TrainCsvCommon extends TrainCommon {
026
027    protected final void printDepartureTime(CSVPrinter printer, String time) throws IOException {
028        printer.printRecord("DT", Bundle.getMessage("csvDepartureTime"), time); // NOI18N
029    }
030
031    protected final void printHeader(CSVPrinter printer) throws IOException {
032        printer.printRecord(Bundle.getMessage("csvOperator"), Bundle.getMessage("csvDescription"),
033                Bundle.getMessage("csvParameters")); // NOI18N
034    }
035
036    protected final void printLocationSwitchListComment(CSVPrinter printer, String comment, String textColorName)
037            throws IOException {
038        printer.printRecord("SWLC", Bundle.getMessage("csvSwitchListComment"), comment, textColorName); // NOI18N
039    }
040
041    protected final void printLocationComment(CSVPrinter printer, String comment, String textColorName)
042            throws IOException {
043        printer.printRecord("LC", Bundle.getMessage("csvLocationComment"), comment, textColorName); // NOI18N
044    }
045
046    protected final void printLocationName(CSVPrinter printer, String name) throws IOException {
047        printer.printRecord("LN", Bundle.getMessage("csvLocationName"), name); // NOI18N
048    }
049
050    protected final void printPrinterName(CSVPrinter printer, String name) throws IOException {
051        printer.printRecord("PRNTR", Bundle.getMessage("csvPrinterName"), name); // NOI18N
052    }
053
054    protected final void printRailroadName(CSVPrinter printer, String name) throws IOException {
055        printer.printRecord("RN", Bundle.getMessage("csvRailroadName"), name); // NOI18N
056    }
057
058    protected final void printRemoveHelpers(CSVPrinter printer) throws IOException {
059        printer.printRecord("RH", Bundle.getMessage("csvRemoveHelpers")); // NOI18N
060    }
061
062    protected final void printRouteLocationComment(CSVPrinter printer, String comment, String textColorName)
063            throws IOException {
064        printer.printRecord("RLC", Bundle.getMessage("csvRouteLocationComment"), comment, textColorName); // NOI18N
065    }
066
067    protected final void printTrainDeparts(CSVPrinter printer, String name, String direction) throws IOException {
068        printer.printRecord("TD", Bundle.getMessage("csvTrainDeparts"), name, direction); // NOI18N
069    }
070
071    protected final void printTrainDescription(CSVPrinter printer, String description) throws IOException {
072        printer.printRecord("TM", Bundle.getMessage("csvTrainManifestDescription"), description); // NOI18N
073    }
074
075    protected final void printTrainLength(CSVPrinter printer, int length, int empty, int total) throws IOException {
076        printer.printRecord("TL", Bundle.getMessage("csvTrainLengthEmptiesCars"), length, empty, total); // NOI18N
077    }
078
079    protected final void printTrainName(CSVPrinter printer, String name) throws IOException {
080        printer.printRecord("TN", Bundle.getMessage("csvTrainName"), name); // NOI18N
081    }
082
083    protected final void printTrainTerminates(CSVPrinter printer, String name) throws IOException {
084        printer.printRecord("TT", Bundle.getMessage("csvTrainTerminates"), name);
085    }
086
087    protected final void printTrainWeight(CSVPrinter printer, int weight) throws IOException {
088        printer.printRecord("TW", Bundle.getMessage("csvTrainWeight"), weight); // NOI18N
089    }
090
091    protected final void printValidity(CSVPrinter printer, String date) throws IOException {
092        printer.printRecord("VT", Bundle.getMessage("csvValid"), date); // NOI18N
093    }
094
095    protected final void printLocationSwitchListComment(CSVPrinter fileOut, Location location) throws IOException {
096        String textColorName = TrainCommon.getTextColorName(location.getSwitchListCommentWithColor());
097        // comment can have multiple lines
098        String[] comments = location.getSwitchListComment().split(NEW_LINE); // NOI18N
099        for (String comment : comments) {
100            printLocationSwitchListComment(fileOut, comment, textColorName);
101        }
102    }
103
104    protected final void printLocationComment(CSVPrinter fileOut, Location location) throws IOException {
105        if (!location.getComment().equals(Location.NONE)) {
106            String textColorName = TrainCommon.getTextColorName(location.getCommentWithColor());
107            // comment can have multiple lines
108            String[] comments = location.getComment().split(NEW_LINE); // NOI18N
109            for (String comment : comments) {
110                printLocationComment(fileOut, comment, textColorName);
111            }
112        }
113    }
114
115    protected final void printRouteLocationComment(CSVPrinter fileOut, RouteLocation rl) throws IOException {
116        if (!rl.getComment().equals(RouteLocation.NONE)) {
117            String textColorName = rl.getCommentTextColor();
118            // comment can have multiple lines
119            String[] comments = rl.getComment().split(NEW_LINE); // NOI18N
120            for (String comment : comments) {
121                printRouteLocationComment(fileOut, comment, textColorName);
122            }
123        }
124    }
125
126    protected final void printTrainComment(CSVPrinter fileOut, Train train) throws IOException {
127        if (!train.getComment().equals(Train.NONE)) {
128            String textColorName = TrainCommon.getTextColorName(train.getCommentWithColor());
129            String[] comments = train.getComment().split(NEW_LINE);
130            for (String comment : comments) {
131                fileOut.printRecord("TC", Bundle.getMessage("csvTrainComment"), comment, textColorName); // NOI18N
132            }
133        }
134    }
135
136    protected final void printRouteComment(CSVPrinter fileOut, Train train) throws IOException {
137        if (!train.getRoute().getComment().isBlank()) {
138            fileOut.printRecord("RC", Bundle.getMessage("csvRouteComment"), train.getRoute().getComment()); // NOI18N
139        }
140    }
141
142    protected void printLogoURL(CSVPrinter fileOut, Train train) throws IOException {
143        String logoURL = FileUtil.getExternalFilename(Setup.getManifestLogoURL());
144        if (!train.getManifestLogoPathName().equals(Train.NONE)) {
145            logoURL = FileUtil.getExternalFilename(train.getManifestLogoPathName());
146        }
147        if (!logoURL.isEmpty()) {
148            fileOut.printRecord("LOGO", Bundle.getMessage("csvLogoFilePath"), logoURL);
149        }
150    }
151
152    protected void printCar(CSVPrinter fileOut, Car car, String code, String message, int count) throws IOException {
153        fileOut.printRecord(code,
154                message,
155                car.getRoadName(),
156                car.getNumber(),
157                car.getTypeName(),
158                car.getLength(),
159                car.getLoadName(),
160                car.getColor(),
161                car.getLocationName(),
162                car.getTrackName(),
163                car.getDestinationName(),
164                car.getDestinationTrackName(),
165                car.getOwnerName(),
166                car.getKernelName(),
167                car.getComment(),
168                car.getPickupComment(),
169                car.getDropComment(),
170                car.isCaboose() ? "C" : "",
171                car.hasFred() ? "F" : "",
172                car.isHazardous() ? "H" : "",
173                car.getRfid(),
174                car.getReturnWhenEmptyDestinationName(),
175                car.getReturnWhenEmptyDestTrackName(),
176                car.isUtility() ? "U" : "",
177                count,
178                car.getFinalDestinationName(),
179                car.getFinalDestinationTrackName(),
180                car.getLoadType(),
181                car.getReturnWhenLoadedDestinationName(),
182                car.getReturnWhenLoadedDestTrackName(),
183                car.getRoutePath(),
184                car.getDivisionName(),
185                car.getBlocking());
186    }
187
188    protected void printEngine(CSVPrinter fileOut, Engine engine, String code, String message) throws IOException {
189        fileOut.printRecord(code,
190                message,
191                engine.getRoadName(),
192                engine.getNumber(),
193                engine.getModel(),
194                engine.getLength(),
195                engine.getTypeName(),
196                engine.getHp(),
197                engine.getLocationName(),
198                engine.getTrackName(),
199                engine.getDestinationName(),
200                engine.getDestinationTrackName(),
201                engine.getOwnerName(),
202                engine.getConsistName(),
203                engine.isLead() ? "Lead loco" : "", // NOI18N
204                engine.getComment(),
205                engine.getRfid(),
206                engine.getDccAddress(),
207                engine.getBlocking());
208    }
209
210    protected final void checkForEngineOrCabooseChange(CSVPrinter fileOut, Train train, RouteLocation rl)
211            throws IOException {
212        if (train.getSecondLegOptions() != Train.NO_CABOOSE_OR_FRED) {
213            if (rl == train.getSecondLegStartRouteLocation()) {
214                engineCsvChange(fileOut, rl, train.getSecondLegOptions());
215            }
216            if (rl == train.getSecondLegEndRouteLocation()) {
217                printRemoveHelpers(fileOut);
218            }
219        }
220        if (train.getThirdLegOptions() != Train.NO_CABOOSE_OR_FRED) {
221            if (rl == train.getThirdLegStartRouteLocation()) {
222                engineCsvChange(fileOut, rl, train.getThirdLegOptions());
223            }
224            if (rl == train.getThirdLegEndRouteLocation()) {
225                printRemoveHelpers(fileOut);
226            }
227        }
228    }
229
230    protected void engineCsvChange(CSVPrinter fileOut, RouteLocation rl, int legOptions) throws IOException {
231        if ((legOptions & Train.HELPER_ENGINES) == Train.HELPER_ENGINES) {
232            fileOut.printRecord("AH", Bundle.getMessage("csvAddHelpers"));
233        }
234        if ((legOptions & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE ||
235                (legOptions & Train.ADD_CABOOSE) == Train.ADD_CABOOSE) {
236            fileOut.printRecord("CC", Bundle.getMessage("csvChangeCaboose"));
237        }
238        if ((legOptions & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES) {
239            fileOut.printRecord("CL", Bundle.getMessage("csvChangeLocos"));
240        }
241    }
242
243    protected void printTrackComments(CSVPrinter fileOut, RouteLocation rl, List<Car> carList) throws IOException {
244        Location location = rl.getLocation();
245        if (location != null) {
246            List<Track> tracks = location.getTracksByNameList(null);
247            for (Track track : tracks) {
248                // any pick ups or set outs to this track?
249                boolean pickup = false;
250                boolean setout = false;
251                for (Car car : carList) {
252                    if (car.getRouteLocation() == rl && car.getTrack() != null && car.getTrack() == track) {
253                        pickup = true;
254                    }
255                    if (car.getRouteDestination() == rl &&
256                            car.getDestinationTrack() != null &&
257                            car.getDestinationTrack() == track) {
258                        setout = true;
259                    }
260                }
261                // print the appropriate comment if there's one
262                // each comment can have multiple lines
263                if (pickup && setout && !track.getCommentBoth().equals(Track.NONE)) {
264                    String textColorName = TrainCommon.getTextColorName(track.getCommentBothWithColor());
265                    String[] comments = track.getCommentBoth().split(NEW_LINE);
266                    for (String comment : comments) {
267                        fileOut.printRecord("TKCB", Bundle.getMessage("csvTrackCommentBoth"), comment, textColorName); // NOI18N
268                    }
269                } else if (pickup && !setout && !track.getCommentPickup().equals(Track.NONE)) {
270                    String textColorName = TrainCommon.getTextColorName(track.getCommentPickupWithColor());
271                    String[] comments = track.getCommentPickup().split(NEW_LINE);
272                    for (String comment : comments) {
273                        fileOut.printRecord("TKCP", Bundle.getMessage("csvTrackCommentPickUp"), comment, textColorName); // NOI18N
274                    }
275                } else if (!pickup && setout && !track.getCommentSetout().equals(Track.NONE)) {
276                    String textColorName = TrainCommon.getTextColorName(track.getCommentSetoutWithColor());
277                    String[] comments = track.getCommentSetout().split(NEW_LINE);
278                    for (String comment : comments) {
279                        fileOut.printRecord("TKCS", Bundle.getMessage("csvTrackCommentSetOut"), comment, textColorName); // NOI18N
280                    }
281                }
282            }
283        }
284    }
285
286    protected void listCarsLocationUnknown(CSVPrinter fileOut) throws IOException {
287        List<Car> cars = InstanceManager.getDefault(CarManager.class).getCarsLocationUnknown();
288        if (cars.isEmpty()) {
289            return; // no cars to search for!
290        }
291        fileOut.printRecord("SMCM", Bundle.getMessage("csvSearchMiaMessage"), Setup.getMiaComment());
292        for (Car car : cars) {
293            printCar(fileOut, car, "SMC", Bundle.getMessage("csvSearchMissingCar"), 0);
294        }
295    }
296}