001package jmri.jmrit.operations.trains.tools;
002
003import java.awt.Frame;
004import java.io.IOException;
005import java.util.ArrayList;
006import java.util.List;
007
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011import jmri.InstanceManager;
012import jmri.jmrit.operations.rollingstock.cars.*;
013import jmri.jmrit.operations.routes.RouteLocation;
014import jmri.jmrit.operations.setup.Control;
015import jmri.jmrit.operations.trains.Train;
016import jmri.jmrit.operations.trains.TrainCommon;
017import jmri.util.davidflanagan.HardcopyWriter;
018
019/**
020 * Print the cars in the train.
021 * <p>
022 * This uses the older style printing, for compatibility with Java 1.1.8 in
023 * Macintosh MRJ
024 *
025 * @author Daniel Boudreau Copyright (C) 2025
026 */
027public class PrintShowCarsInTrain extends TrainCommon {
028
029    static final String NEW_LINE = "\n"; // NOI18N
030
031    CarManager carManager = InstanceManager.getDefault(CarManager.class);
032    static int fieldSize =
033            InstanceManager.getDefault(CarRoads.class).getMaxNameLength() + Control.max_len_string_road_number;
034    static final String TAB = padString("", fieldSize);
035
036    /**
037     * Prints the block order for a train at the train's current location.
038     * 
039     * @param train     the train.
040     * @param isPreview if true preview, otherwise print
041     */
042    public void printCarsInTrain(Train train, boolean isPreview) {
043        if (train.isBuilt()) {
044            // obtain a HardcopyWriter to do this
045            try (HardcopyWriter writer =
046                    new HardcopyWriter(new Frame(), Bundle.getMessage("TitleShowCarsInTrain", train.getName()),
047                            Control.reportFontSize, .5,
048                            .5, .5, .5, isPreview);) {
049
050                printCarsAtLocation(writer, train, train.getCurrentRouteLocation());
051
052            } catch (HardcopyWriter.PrintCanceledException ex) {
053                log.debug("Print cancelled");
054            } catch (IOException ex) {
055                log.error("Error printing car roster: {}", ex.getLocalizedMessage());
056            }
057        }
058    }
059
060    public void printCarsAtLocation(HardcopyWriter writer, Train train, RouteLocation rl) throws IOException {
061        if (rl != null) {
062            log.debug("RouteLocation rl: {}", rl.getName());
063            // print location name followed by header
064            writer.write(rl.getSplitName() + NEW_LINE);
065            writer.write(getHeader());
066            for (RouteLocation rld : train.getRoute().getBlockingOrder()) {
067                log.debug("RouteLocation rld: {}", rld.getName());
068                for (Car car : carManager.getByTrainDestinationList(train)) {
069                    if (isNextCar(car, rl, rld, true)) {
070                        log.debug("car ({}) routelocation ({}) track ({}) route destination ({})",
071                                car.toString(), car.getRouteLocation().getName(),
072                                car.getTrackName(), car.getRouteDestination().getName());
073                        String s = getCarId(car) + NEW_LINE;
074                        if (car.getRouteDestination() == rl) {
075                            writer.write(TAB + TAB + s); // set out
076                        } else if (car.getRouteLocation() == rl && car.getTrack() != null) {
077                            writer.write(s); // pick up
078                        } else {
079                            writer.write(TAB + s); // in train
080                        }
081                    }
082                }
083            }
084        }
085    }
086
087    /**
088     * Prints the block order for a train for each station starting at the
089     * train's current location.
090     * 
091     * @param train     the train.
092     * @param isPreview if true preview, otherwise print
093     */
094    public void printCarsInTrainRoute(Train train, boolean isPreview) {
095        if (train.isBuilt()) {
096            // obtain a HardcopyWriter to do this
097            try (HardcopyWriter writer =
098                    new HardcopyWriter(new Frame(), Bundle.getMessage("TitleShowCarsInTrain", train.getName()),
099                            Control.reportFontSize, .5,
100                            .5, .5, .5, isPreview);) {
101                printCarsRoute(writer, train);
102            } catch (HardcopyWriter.PrintCanceledException ex) {
103                log.debug("Print cancelled");
104            } catch (IOException ex) {
105                log.error("Error printing car roster: {}", ex.getLocalizedMessage());
106            }
107        }
108    }
109
110    public void printCarsRoute(HardcopyWriter writer, Train train) throws IOException {
111        loadCarsInTrain(train);
112        // start printing at the train's current location
113        boolean foundTrainLoc = false;
114        for (RouteLocation rl : train.getRoute().getLocationsBySequenceList()) {
115            if (rl != null) {
116                if (!foundTrainLoc && rl != train.getCurrentRouteLocation()) {
117                    continue;
118                }
119                foundTrainLoc = true;
120                log.debug("RouteLocation rl: {}", rl.getName());
121                // print location name followed by header
122                writer.write(rl.getSplitName() + NEW_LINE);
123                if (isThereWorkAtLocation(carManager.getByTrainDestinationList(train), null, rl)) {
124                    writer.write(getHeader());
125                    printCars(writer, train, rl);
126                    writer.write(NEW_LINE);
127                }
128            }
129        }
130    }
131
132    List<Car> carsInTrain = new ArrayList<>();
133
134    private void printCars(HardcopyWriter writer, Train train, RouteLocation rl) throws IOException {
135        for (Car car : carManager.getByTrainDestinationList(train)) {
136            if (car.getRouteLocation() == rl && !carsInTrain.contains(car)) {
137                carsInTrain.add(car);
138                writer.write(getCarId(car) + NEW_LINE); // pick up
139            } else if (car.getRouteDestination() == rl) {
140                carsInTrain.remove(car);
141                writer.write(TAB + TAB + getCarId(car) + NEW_LINE); // set out
142            } else if (carsInTrain.contains(car)) {
143                writer.write(TAB + getCarId(car) + NEW_LINE); // in train
144            }
145        }
146    }
147
148    private void loadCarsInTrain(Train train) {
149        carsInTrain.clear();
150        for (Car car : carManager.getByTrainDestinationList(train)) {
151            if (car.getTrack() == null) {
152                carsInTrain.add(car);
153            }
154        }
155    }
156
157    private String getCarId(Car car) {
158        return car.getRoadName().split(HYPHEN)[0] +
159                " " +
160                splitString(car.getNumber());
161    }
162
163    private String getHeader() {
164        int fieldSize =
165                InstanceManager.getDefault(CarRoads.class).getMaxNameLength() + Control.max_len_string_road_number;
166        String header = padString(Bundle.getMessage("Pickup"), fieldSize) +
167                padString(Bundle.getMessage("InTrain"), fieldSize) +
168                padString(Bundle.getMessage("SetOut"), fieldSize) +
169                NEW_LINE;
170        return header;
171    }
172
173    private final static Logger log = LoggerFactory.getLogger(PrintShowCarsInTrain.class);
174}