/** Return a list containing all trains which are in the Block with given id. */
 public ArrayList<Train> getTrainsInBlock(int id) {
   ArrayList<Train> tempAL = new ArrayList<Train>();
   for (int i = 0; i < trainList.size(); i++) {
     if (trainList.get(i).positionBlock.id == id) {
       tempAL.add(trainList.get(i));
     }
   }
   return tempAL;
 }
 /** Load the list of trains which the module will use. */
 public void setTrainList(ArrayList<Train> trainList) {
   this.trainList = trainList;
   if ((trainList != null) && (trainList.size() > 0)) {
     idArray = new String[trainList.size()];
     for (int i = 0; i < trainList.size(); i++) {
       idArray[i] = new String(trainList.get(i).stringId);
     }
   } else {
     idArray = null;
   }
 }
  /** Updates all train data and refreshes the GUI. */
  public static void timeTick(Date date, int delta) {
    if (!isPaused) {
      refreshUI += delta;
      double time = date.getHours() * 60 * 60 + date.getMinutes() * 60 + date.getSeconds();

      for (int i = 0; i < trainList.size(); i++) {
        // Update the data for each train.
        boolean isSelectedByTNC = false;
        if (!isSolo) {
          isSelectedByTNC = tncUI.uiSelect(trainList.get(i).id);
        }
        trainList.get(i).timeTick(time, ((double) (delta)) / 1000.0, isSolo, isSelectedByTNC);
      }

      if (refreshUI >= 1000) {
        // Refresh the train module GUI.

        if (isSolo) {
          // If TNM is running solo, figure out the new time.
          soloTime += 1;
          if (soloTime >= 24 * 60 * 60) {
            soloTime = soloTime % (24 * 60 * 60);
          }
          int hrs = (int) soloTime / (60 * 60);
          int min = ((int) soloTime / 60) % 60;
          int sec = (int) soloTime - (hrs * 60 * 60 + min * 60);
          soloDate = new Date(93, 2, 2, hrs, min, sec);
        } else {
          soloTime = time;
        }

        refreshUI = refreshUI % 1000;
        setSelectedId(selectedId);
      }
    }
  }
  /** Called when run from the command line. The train module will run (mostly) individually. */
  public static void main(String[] args) {
    try {
      isSolo = true;

      // Get the number of trains.
      if (args.length != 1) {
        System.out.println("Invalid number of arguments.");
        System.exit(1);
      }
      soloNumTrains = Integer.parseInt(args[0], 10);
      if ((soloNumTrains < 1) || (soloNumTrains > 9)) {
        System.out.println(
            "Invalid argument. The number of trains must be greater than 0 and less than 10.");
        System.exit(1);
      }

      // Create the test block loop.
      Block bYard =
          new Block(
              0, "A", "I", 0.0, 0.0, 5.0, true, false, true, false, false, "", false, false, false);
      Block b01 =
          new Block(
              1, "B", "II", 500.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b02 =
          new Block(
              2, "C", "II", 500.0, -22.2, 1.0, true, false, false, false, false, "", false, false,
              false);
      Block b03 =
          new Block(
              3, "D", "II", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b04 =
          new Block(
              4, "E", "II", 500.0, 11.1, 30.0, true, true, false, false, false, "", false, false,
              false);
      Block b05 =
          new Block(
              5, "F", "III", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b06 =
          new Block(
              6, "G", "III", 100.0, 0.0, 5.0, true, false, false, true, false, "Alpha", false,
              false, false);
      Block b07 =
          new Block(
              7, "H", "III", 500.0, -11.1, 30.0, true, false, false, false, false, "", false, false,
              false);
      Block b08 =
          new Block(
              8, "I", "III", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b09 =
          new Block(
              9, "J", "IV", 500.0, 22.2, 1.0, true, false, false, false, false, "", false, false,
              false);
      Block b10 =
          new Block(
              10, "K", "IV", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b11 =
          new Block(
              11, "L", "IV", 100.0, 0.0, 5.0, true, false, false, true, false, "Beta", false, false,
              false);
      Block b12 =
          new Block(
              12, "M", "IV", 50.0, 11.1, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b13 =
          new Block(
              13, "N", "V", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b14 =
          new Block(
              14, "O", "V", 50.0, -11.1, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b15 =
          new Block(
              15, "P", "V", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);
      Block b16 =
          new Block(
              16, "Q", "V", 100.0, 0.0, 5.0, true, false, false, true, false, "Gamma", false, false,
              false);
      Block b17 =
          new Block(
              17, "R", "V", 50.0, 0.0, 15.0, true, false, false, false, false, "", false, false,
              false);

      bYard.connect(b17, b01);
      b01.connect(bYard, b02);
      b02.connect(b01, b03);
      b03.connect(b02, b04);
      b04.connect(b03, b05);
      b05.connect(b04, b06);
      b06.connect(b05, b07);
      b07.connect(b08, b06);
      b08.connect(b09, b07);
      b09.connect(b10, b08);
      b10.connect(b11, b09);
      b11.connect(b12, b10);
      b12.connect(b11, b13);
      b13.connect(b14, b12);
      b14.connect(b13, b15);
      b15.connect(b16, b14);
      b16.connect(b15, b17);
      b17.connect(bYard, b16);

      ArrayList<Block> route = new ArrayList<Block>();
      route.add(bYard);
      route.add(b01);
      route.add(b02);
      route.add(b03);
      route.add(b04);
      route.add(b05);
      route.add(b06);
      route.add(b07);
      route.add(b08);
      route.add(b09);
      route.add(b10);
      route.add(b11);
      route.add(b12);
      route.add(b13);
      route.add(b14);
      route.add(b15);
      route.add(b16);
      route.add(b17);
      route.add(bYard);
      route.add(b01);
      route.add(b02);
      route.add(b03);
      route.add(b04);
      route.add(b05);
      route.add(b06);
      route.add(b07);
      route.add(b08);
      route.add(b09);
      route.add(b10);
      route.add(b11);
      route.add(b12);
      route.add(b13);
      route.add(b14);
      route.add(b15);
      route.add(b16);
      route.add(b17);
      route.add(bYard);

      /*
       * Create the trains.
       * The first will depart at 8:00 AM, the second at 8:30 AM, the third at 9:00 AM, etc.
       * The first will depart at 8:00 AM, the second at 8:15 AM, the third at 8:30 AM, etc.
       * All will have break time set to 4 hours after their departure times.
       */
      trainList = new ArrayList<Train>();
      idArray = new String[soloNumTrains];
      for (int i = 0; i < soloNumTrains; i++) {
        trainList.add(
            new Train(
                i + 1,
                "T" + (i + 1),
                "Test",
                (8 * 60 * 60 + i * 15 * 60) % (24 * 60 * 60),
                route,
                new Engineer(
                    true, false, 0.0, (8 * 60 * 60 + i * 15 * 60 + 5 * 60) % (24 * 60 * 60)),
                bYard));
        idArray[i] = new String("T" + (i + 1));
      }

      // Create the UI.
      TrainModelUI tnmUI = new TrainModelUI();
      tnmUI.setTrainList(trainList);

      // Setup the timer.
      soloTime = 7 * 60 * 60 + 59 * 60 + 55;
      soloDate = new Date(93, 2, 2, 7, 59, 55);
      ActionListener taskPerformer =
          new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
              timeTick(soloDate, soloDelta);
            }
          };
      new javax.swing.Timer(20, taskPerformer).start();

      // Disable all "Toggle" buttons that are associated with a manual entry.
      btnToggleManRecPower.setEnabled(false);
      btnToggleManDesSpdLmt.setEnabled(false);
      btnToggleManLights.setEnabled(false);
      btnToggleManDoors.setEnabled(false);
      btnToggleManTarTemperature.setEnabled(false);

      // Make it so only manual values are used.
      for (int i = 0; i < soloNumTrains; i++) {
        Train t = trainList.get(i);
        t.issetManualPower = true;
        t.issetManualSpeedLimit = true;
        t.issetLightsOnUseManual = true;
        t.issetDoorsOpenUseManual = true;
        t.issetTargetTemperatureManual = true;
      }

      btnPauseResume.setEnabled(true);
      tnmUI.setSelectedId(trainList.get(0).id);
      tnmUI.setIsPaused(tnmUI.getIsPaused());
      tnmUI.setIsVisible(true);
    } catch (Exception e) {
      e.printStackTrace(System.err);
      JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
    }
  }
  /**
   * Update the GUI (both the dynamic and static windows) so that it displays the data of the newly
   * selected train.
   */
  public static void setSelectedId(int selId) {
    selectedId = selId;
    dynamicWindow.setTitle(
        "Train Model (Chris Paskie)   -   UI   (Train ID:   "
            + trainList.get(selectedId - 1).stringId
            + ")");
    staticWindow.setTitle(
        "Train Model (Chris Paskie)   -   Static Values   (Train ID:   "
            + trainList.get(selectedId - 1).stringId
            + ")");
    int hrs = (int) soloTime / (60 * 60);
    int min = ((int) soloTime / 60) % 60;
    int sec = (int) soloTime - (hrs * 60 * 60 + min * 60);
    jlTime.setText(
        ((hrs < 10) ? "0" : "")
            + hrs
            + ":"
            + ((min < 10) ? "0" : "")
            + min
            + ":"
            + ((sec < 10) ? "0" : "")
            + sec);

    jlCurVel.setText("" + trainList.get(selectedId - 1).curVelocity);
    jlCurAccel.setText("" + trainList.get(selectedId - 1).curAccel);
    jlRecPowerTNC.setText("" + trainList.get(selectedId - 1).receivedPower);
    jlManRecPower.setText("" + trainList.get(selectedId - 1).manualPower);
    jlToggleManRecPower.setText("" + trainList.get(selectedId - 1).issetManualPower);
    jlPostedSpdLmt.setText("" + trainList.get(selectedId - 1).postedSpeedLimit);
    jlManDesSpdLmt.setText("" + trainList.get(selectedId - 1).manualSpeedLimit);
    jlToggleManDesSpdLmt.setText("" + trainList.get(selectedId - 1).issetManualSpeedLimit);
    jlGrade.setText("" + trainList.get(selectedId - 1).getRelativeGrade());
    jlTotalMass.setText("" + trainList.get(selectedId - 1).totalMass);
    jlPassengerCount.setText("" + trainList.get(selectedId - 1).numPassengers);
    jlCrewCount.setText("" + trainList.get(selectedId - 1).numCrew);
    jlPosition.setText(
        ""
            + ((trainList.get(selectedId - 1).issetSignalPickupFailure)
                ? "???????"
                : ("[ "
                    + trainList.get(selectedId - 1).positionBlock.id
                    + " , "
                    + trainList.get(selectedId - 1).positionMeters
                    + " ]")));
    jlToggleSignalPickupFailure.setText(
        "" + trainList.get(selectedId - 1).issetSignalPickupFailure);
    jlToggleEngineFailure.setText("" + trainList.get(selectedId - 1).issetEngineFailure);
    jlToggleBrakeFailure.setText("" + trainList.get(selectedId - 1).issetBrakeFailure);
    jlToggleServiceBrake.setText("" + trainList.get(selectedId - 1).issetServiceBrake);
    jlToggleEmergencyBrake.setText("" + trainList.get(selectedId - 1).issetEmerBrake);
    jlLights.setText("" + ((trainList.get(selectedId - 1).issetLightsOn) ? "On" : "Off"));
    jlManLights.setText("" + ((trainList.get(selectedId - 1).issetLightsOnManual) ? "On" : "Off"));
    jlToggleManLights.setText("" + trainList.get(selectedId - 1).issetLightsOnUseManual);
    jlDoors.setText("" + ((trainList.get(selectedId - 1).issetDoorsOpen) ? "Open" : "Closed"));
    jlManDoors.setText(
        "" + ((trainList.get(selectedId - 1).issetDoorsOpenManual) ? "Open" : "Closed"));
    jlToggleManDoors.setText("" + trainList.get(selectedId - 1).issetDoorsOpenUseManual);
    jlCurTemperature.setText("" + trainList.get(selectedId - 1).curTemperature);
    jlTarTemperature.setText("" + trainList.get(selectedId - 1).targetTemperatureTNC);
    jlManTarTemperature.setText("" + trainList.get(selectedId - 1).targetTemperatureManual);
    jlToggleManTarTemperature.setText(
        "" + trainList.get(selectedId - 1).issetTargetTemperatureManual);
    jlAnnouncement.setText("" + trainList.get(selectedId - 1).announcement);

    jlLength.setText("" + trainList.get(selectedId - 1).length);
    jlWidth.setText("" + trainList.get(selectedId - 1).width);
    jlHeight.setText("" + trainList.get(selectedId - 1).height);
    jlNumCars.setText("" + trainList.get(selectedId - 1).numCars);
    jlMotorPower.setText("" + trainList.get(selectedId - 1).motorPower);
    jlMaxSpeed.setText("" + trainList.get(selectedId - 1).maxSpeed);
    jlServiceBrakeDecel.setText("" + trainList.get(selectedId - 1).serviceBrakeDecel);
    jlEmergencyBrakeDecel.setText("" + trainList.get(selectedId - 1).emerBrakeDecel);
    jlFrictionCoeff.setText("" + trainList.get(selectedId - 1).frictionCoeff);
    jlEmptyTrainMass.setText("" + trainList.get(selectedId - 1).emptyTrainMass);
    jlPersonMass.setText("" + trainList.get(selectedId - 1).personMass);
    jlMaxSeatedCount.setText("" + trainList.get(selectedId - 1).maxCapacitySeated);
    jlMaxStandingCount.setText("" + trainList.get(selectedId - 1).maxCapacityStanding);
    jlMaxCrewCount.setText("" + trainList.get(selectedId - 1).maxCapacityCrew);
  }