-- environment_ers.lua
if S.trains == nil then S.trains = {} end
if S.train_duration == nil then S.train_duration = {} end
if S.yards == nil then S.yards = {} end

F.known_rcs = {
  ["LILSHUNTER"] = "LILSHUNTER",
  ["CRYSTAL"] = "CRYSTAL",
  ["DEPOTUNLOADING"] = "DEPOTUNLOADING",
  ["ERSBALLASTLOAD"] = "ERSBALLASTLOAD",
  ["CORNUNLOAD"] = "CORNUNLOAD",
  ["MEGACORNLOAD"] = "MEGACORNLOAD",
  ["XERXES"] = "XERXES",
  ["BLOCK"] = "BLOCK",
  ["FERTILIZER"] = "FERTILIZER",
  ["FERTRUNNER"] = "FERTRUNNER",
  ["MULCH"] = "MULCH",
  ["ERSTAZIDEPOTUNLOAD"] = "ERSTAZIDEPOTUNLOAD",
  ["ERSTAZIDEPOT"] = "ERSTAZIDEPOT",
  ["ERSSINENSISDEPOT"] = "ERSSINENSISDEPOT",
  ["ERSTAZITST"] = "ERSTAZITST",
  ["FACTORY"] = "FACTORY",
  ["OILEXTRACT"] = "OILEXTRACT",
  ["SHUNT04A"] = "SHUNT04A",
  ["ERSTAZISHOP"] = "ERSTAZISHOP",
  ["TYARD"] = "TYARD",
  ["TY_COLLECT_SINESIS"] = "TY_COLLECT_SINESIS",
  ["TY_RTS"] = "TY_RTS",
  ["FAREAST"] = "FAREAST",
  ["KLYARD"] = "KLYARD",
}

F.print = function (str) if F.debug then print("".. (str or "nil") ) end end
F.isempty = function (s) return s == nil or s == "" end
F.get_rc_safe = function() return get_rc() or "" end
F.get_line_safe = function() return get_line() or "" end
F.get_train_length_safe = function() return train_length() or 0 end
F.avg = function(t)
  local sum = 0
  local count = 0
  for k,v in pairs(t) do
    if type(v) == "number" then
      sum = sum + v
      count = count + 1
    end
  end
  return (sum / count)
end

if event.init then
  F.debug = true
  F.max_displays = 52
  F.print("Initialized")
end

F.clear_main_depot_displays = function() for i = 1, F.max_displays, 1 do digiline_send("train_display" .. i, " ") end end

--[[
  EXAMPLE: F.has_rc("LILSHUNTER", F.get_rc_safe() )
  Merged F.has_rc and F.does_train_have_rc
  F.does_train_have_rc is deprecated
]]
F.has_rc = function(query,rc_list) -- query = string, single entry
  for word in rc_list:gmatch("[^%s]+") do
    if word == query then return true end
  end
  return false
end

F.send_route = function(passive_name, route, show_print)
  local message = ""
  local return_value = false
  if can_set_route(passive_name, route) then
    set_route(passive_name, route)
    message = passive_name .. " has been set to " .. route
    return_value = true
  else
    message = route .. " cannot be set for " .. passive_name .. ". Try another."
    return_value = false
  end
  if show_print == true then F.print(message) end
  return return_value
end

F.save_train = function()
  if not atc_id then return end
  if S.trains then
    S.trains[atc_id] = { ["id"] = atc_id, ["rc"] = F.get_rc_safe(), ["ln"] = F.get_line_safe(), ["cars_count"] = F.get_train_length_safe() }
  end
end

F.get_real_split_count = function(train_length_count, split_count)
  if split_count then
    if split_count == "all" then
      return 2
    else
      F.print("train_length_count (" .. train_length_count .. ") - split_count (" .. split_count .. ")")
      train_length_count = train_length_count + 1
      split_count = train_length_count - split_count
      return split_count
    end
  else
    return nil
  end
end

F.yard_siding_basic = function(yard, name, place)
  if event.train then
    if not atc_id then return end
    F.save_train()
    if place == "start" then
      if atc_arrow then
        atc_send("S5")
      else
        atc_send("B5S5")
      end
    elseif place == "end_alt" then
      do_something = false
    elseif place == "end" then
      if atc_arrow then
        atc_send("B0 W R")
      end
    else
      F.print("Place for " .. name .. " has not been defined")
    end
  end
end

F.yard_set_route = function(yard, train_id, atc_command)
  if atc_command == nil then atc_command = "A1 S5" end
  if S.yards[yard] and S.yards[yard]["state"] and S.yards[yard]["actions"] then
    status = S.yards[yard]["state"]["status"]
    current_sequence = S.yards[yard]["state"]["current"]
    current_operation = S.yards[yard]["actions"][current_sequence]["operation"]
    table_count = table.maxn(S.yards[yard]["actions"])
    next_sequence = current_sequence + 1
    -- F.print(next_sequence .. "/" .. table_count)
    if next_sequence <= table_count and S.yards[yard]["actions"][next_sequence] and  S.yards[yard]["actions"][next_sequence]["route"] then
      next_route = S.yards[yard]["actions"][next_sequence]["route"]
      next_operation = S.yards[yard]["actions"][next_sequence]["operation"]
      use_this_signal = S.yards[yard]["actions"][next_sequence]["signal"]
      atc_send_status = atc_send_to_train(train_id, atc_command)
      if atc_send_status then
        if use_this_signal == nil then
          F.print(train_id .. " is waiting at: nil")
          --[[
            Maybe change it so it shows which signal it is
            waiting at when completed with this message:
            F.print(train_id .. " has finished the sequences and is waiting.")
          ]]
        else
          can_set_route_response = can_set_route(use_this_signal, next_route)
          if can_set_route_response then
            -- set_train_length_count = S.yards[yard]["state"]["train_length_count"]
            -- S.yards[yard]["state"] = { status = "moving", current = next_sequence, train_length_count = set_train_length_count }
            set_route(use_this_signal, next_route)
            F.print("DIRECT COMMAND current_operation: " .. current_operation .. " next_operation: " .. next_operation)
            F.print(train_id .. " is heading to " .. next_route .. " through " .. use_this_signal)
          else
            F.print(train_id .. " cannot go to " .. next_route .. " at " .. use_this_signal)
          end
        end
      else
        F.print(atc_command .. " command failed")
      end
    else
      F.print("End of Operations for " .. train_id)
    end
  end
end

F.yard_siding_next_operation = function(yard, train_id, current_sequence)
  if S.yards[yard]["state"] then
    if current_sequence == nil then current_sequence = S.yards[yard]["state"]['current'] end
    local next_sequence = current_sequence + 1
    local set_train_length_count = S.yards[yard]["state"]["train_length_count"]
    local table_count = table.maxn(S.yards[yard]["actions"])
    F.print(next_sequence .. "/" .. table_count)
    S.yards[yard]["state"]["current"] = next_sequence
  end
end

F.yard_siding_operations_start = function(yard, train_id, place, current_operation, next_operation, current_split_count)
  -- F.print("THIS IS " .. place)
  if atc_arrow then
    if current_operation == "split_at_engine" then
      unset_autocouple()
      -- split_off_locomotive("A0B0")
      split_at_index(current_split_count, "S0")
      F.yard_set_route(yard, train_id, atc_command)
      F.yard_siding_next_operation(yard, train_id)
    -- elseif current_operation == "reverse" then
      -- unset_autocouple()
      -- atc_send("B0 W R S5")
    elseif next_operation == "split_at_engine" then
      F.print("MAYBE SPLIT HERE AT " .. place .. " current: " .. current_operation .. " next: " .. next_operation)
      F.yard_set_route(yard, train_id, atc_command)
      F.yard_siding_next_operation(yard, train_id)
    else
      F.yard_set_route(yard, train_id, atc_command)
      F.yard_siding_next_operation(yard, train_id)
    end
  else
    if current_split_count == nil then
      F.print("YARD SIDING " .. place .. " current_operation: " .. current_operation .. " next_operation: " .. next_operation)
    end
    if current_operation == "autocouple" then
      set_autocouple()
    elseif current_operation == "split_at_engine" then
      set_autocouple()
    else
      unset_autocouple()
    end

    if next_operation == "forward" then
      F.print("at start and the next operation says forward")
      F.yard_set_route(yard, train_id, atc_command)
      F.yard_siding_next_operation(yard, train_id)
    end
  end
end

F.yard_siding_operations_end = function(yard, train_id, place, current_operation, next_operation, current_split_count)
  -- F.print("THIS IS " .. place)
  if atc_arrow then
    F.print("YARD SIDING " .. place .. " current_operation: " .. current_operation .. " next_operation: " .. next_operation)
    if current_operation == "split_at_engine" then
      -- split_at_index(2, "S0")
      -- F.yard_set_route(yard, train_id, nil)
      -- F.yard_siding_next_operation(yard, train_id)
      unset_autocouple()
      atc_send("B0 W R S5")
      -- split_at_index(2, "S0")
    elseif next_operation == "autocouple" then
      unset_autocouple()
      atc_send("B0 W R S5")
    elseif next_operation == "reverse" then
      unset_autocouple()
      atc_send("B0 W R S5")
    elseif next_operation == "forward" then
      unset_autocouple()
      F.yard_set_route(yard, train_id, nil)
      F.yard_siding_next_operation(yard, train_id)
    else
      unset_autocouple()
      atc_send("B0 W R S5")
    end
  else
    if next_operation == "autocouple" then
      set_autocouple()
    end
    if current_operation == "autocouple" then
      set_autocouple()
    end
    -- if next_operation == "split_at_engine" then
      -- F.yard_siding_next_operation(yard, train_id)
    -- end
  end
end

F.yard_siding_operations_end_alt = function(yard, train_id, place, current_operation, next_operation, current_split_count)
  -- F.print("THIS IS " .. place)
  if atc_arrow then
    if next_operation == "forward" or next_operation == "split_at_engine" then
      unset_autocouple()
      F.yard_set_route(yard, train_id, nil)
      F.yard_siding_next_operation(yard, train_id)
    elseif next_operation == "autocouple" then
      set_autocouple()
      F.yard_set_route(yard, train_id, nil)
      F.yard_siding_next_operation(yard, train_id)
    elseif next_operation == "reverse" then
      unset_autocouple()
      atc_send("B0 W R S5")
    else
      unset_autocouple()
      -- atc_send("B0 W R S5")
      F.print("At " .. place .. " and stopped because the command isn't programmed yet")
    end
  end
end

F.yard_siding_operations = function(yard, train_id, place, current_operation, next_operation, current_split_count)
  if place == "start" then
    F.yard_siding_operations_start(yard, train_id, place, current_operation, next_operation, current_split_count)
  elseif place == "end" then
    F.yard_siding_operations_end(yard, train_id, place, current_operation, next_operation, current_split_count)
  elseif place == "end_alt" then
    F.yard_siding_operations_end_alt(yard, train_id, place, current_operation, next_operation, current_split_count)
  else
    F.print("Place for " .. name .. " has not been defined")
  end
end

F.yard_siding = function(yard, name, place)
  if event.train then
    if not atc_id then return end
    if F.has_rc("LILSHUNTER", F.get_rc_safe() ) then
      if S.yards[yard] and S.yards[yard]["state"] and S.yards[yard]["actions"] then
        train_id = atc_id
        S.yards[yard]["state"]["train_length_count"] = F.get_train_length_safe()
        train_length_count = S.yards[yard]["state"]["train_length_count"]
        status = S.yards[yard]["state"]["status"]
        current_sequence = S.yards[yard]["state"]["current"]
        current_operation = S.yards[yard]["actions"][current_sequence]["operation"]
        current_split_count = S.yards[yard]["actions"][current_sequence]["split_count"]
        current_split_count = F.get_real_split_count(train_length_count, current_split_count)
        table_count = table.maxn(S.yards[yard]["actions"])
        next_sequence = current_sequence + 1
        if next_sequence <= table_count and S.yards[yard]["actions"][next_sequence] then
          next_route = S.yards[yard]["actions"][next_sequence]["route"]
          use_this_signal = S.yards[yard]["actions"][next_sequence]["signal"]
          next_operation = S.yards[yard]["actions"][next_sequence]["operation"]
          next_split_count = S.yards[yard]["actions"][next_sequence]["split_count"]
          next_split_count = F.get_real_split_count(train_length_count, next_split_count)
          F.yard_siding_operations(yard, train_id, place, current_operation, next_operation, current_split_count)
        else
          F.print("Went over the table count in F.yard_siding")
        end
      else
        F.yard_siding_basic(yard, name, place)
      end
    else
      F.yard_siding_basic(yard, name, place)
    end
  end
  return
end

F.yard_run = function(yard, section_id) -- section_id example: "723167"
  if S.yards[yard] and type(S.yards[yard]) == "table" then
    section_occuppied_by_table = section_occupancy(section_id)
    section_occuppied_count = table.maxn(section_occuppied_by_table)
    if section_occuppied_count == 1 then
      train_id = section_occuppied_by_table[1]
      F.print("train_id: " .. train_id)
      F.yard_set_route(yard, train_id)
      F.yard_siding_next_operation(yard, train_id)
    else
      F.print("HALT! More than one train is in the SHUNT01 section")
    end
  else
    F.print("ERROR: S.yards[yard] needs to be a table")
  end
  return
end

F.reset_trial_setup = function()
  local yard = "ers_main"
  if S.yards[yard] then
    S.yards[yard] = {}
    F.print(yard .. " has been reset!")
  end
end

F.trial_setup = function(type)
  -- LILSHUNTER
  local yard = "ers_main"
  local section_id = "723167"
  if type == nil then
    F.print("Please, declare a type")
  elseif type == "autocouple_1_4" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "SIDING01", signal = "SHUNT01_SIGNAL", operation = "autocouple"},
        [3] = {route = "HEADSHUNT01", signal = "SIDING01_SIGNAL", operation = "reverse"},
        [4] = {route = "SIDING02", signal = "HEADSHUNT01_SIGNAL", operation = "autocouple"},
        [5] = {route = "HEADSHUNT01", signal = "SIDING02_SIGNAL", operation = "reverse"},
        [6] = {route = "SIDING03", signal = "HEADSHUNT01_SIGNAL", operation = "autocouple"},
        [7] = {route = "HEADSHUNT01", signal = "SIDING03_SIGNAL", operation = "reverse"},
        [8] = {route = "SIDING04", signal = "HEADSHUNT01_SIGNAL", operation = "autocouple"},
        [9] = {route = "HEADSHUNT01", signal = "SIDING04_SIGNAL", operation = "reverse"},
        [10] = {route = "SIDING05", signal = "HEADSHUNT01_SIGNAL", operation = "split_at_engine", split_count = "all"},
        [11] = {route = "SHUNT01", signal = "SIDING05_SIGNAL", operation = "forward"},
        [12] = {route = "SHUNT01", signal = nil, operation = "end"}
      }
    }
  elseif type == "split_train_1_4" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "SIDING05", signal = "SHUNT01_SIGNAL", operation = "autocouple"},
        [3] = {route = "HEADSHUNT01", signal = "SIDING05_SIGNAL", operation = "reverse"},
        [4] = {route = "SIDING04", signal = "HEADSHUNT01_SIGNAL", operation = "split_at_engine", split_count = 1},
        [5] = {route = "HEADSHUNT01", signal = "SIDING04_SIGNAL", operation = "reverse"},
        [6] = {route = "SIDING03", signal = "HEADSHUNT01_SIGNAL", operation = "split_at_engine", split_count = 1},
        [7] = {route = "HEADSHUNT01", signal = "SIDING03_SIGNAL", operation = "reverse"},
        [8] = {route = "SIDING02", signal = "HEADSHUNT01_SIGNAL", operation = "split_at_engine", split_count = 1},
        [9] = {route = "HEADSHUNT01", signal = "SIDING02_SIGNAL", operation = "reverse"},
        [10] = {route = "SIDING01", signal = "HEADSHUNT01_SIGNAL", operation = "split_at_engine", split_count = 1},
        [11] = {route = "SHUNT01", signal = "SIDING01_SIGNAL", operation = "reverse"},
        [12] = {route = "SHUNT01", signal = nil, operation = "end"}
      }
    }
  elseif type == "loop_test" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "SIDING05", signal = "SHUNT01_SIGNAL", operation = "autocouple"},
        [3] = {route = "ALTSIDING01", signal = "SIDING05_SIGNAL", operation = "reverse"},
        [4] = {route = "SIDING05", signal = "ALTSIDING01_BACK", operation = "forward"},
        [5] = {route = "SHUNT01", signal = "SIDING05_SIGNAL", operation = "split_at_engine", split_count = 4},
        [6] = {route = "SHUNT01", signal = nil, operation = "end"}
      }
    }
  elseif type == "loop_test1" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "SIDING05", signal = "SHUNT01_SIGNAL", operation = "autocouple"},
        [3] = {route = "ALTSIDING01", signal = "SIDING05_SIGNAL", operation = "reverse"},
        [4] = {route = "SIDING05", signal = "ALTSIDING01_BACK", operation = "forward"},
        [5] = {route = "SHUNT01", signal = "SIDING05_SIGNAL", operation = "split_at_engine", split_count = 4},
        [6] = {route = nil, signal = nil, operation = "forward"},
        [7] = {route = nil, signal = nil, operation = "end"}
      }
    }
  elseif type == "loop_autocouple_1_4" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "ALTSIDING01", signal = "SHUNT01_SIGNAL", operation = "forward"},
        [3] = {route = "SIDING01", signal = "ALTSIDING01_BACK", operation = "autocouple"},
        [4] = {route = "ALTSIDING01", signal = "SIDING01_SIGNAL", operation = "forward"},
        [5] = {route = "SIDING02", signal = "ALTSIDING01_BACK", operation = "autocouple"},
        [6] = {route = "ALTSIDING01", signal = "SIDING02_SIGNAL", operation = "forward"},
        [7] = {route = "SIDING03", signal = "ALTSIDING01_BACK", operation = "autocouple"},
        [8] = {route = "ALTSIDING01", signal = "SIDING03_SIGNAL", operation = "forward"},
        [9] = {route = "SIDING04", signal = "ALTSIDING01_BACK", operation = "autocouple"},
        [10] = {route = nil, signal = nil, operation = "forward"},
        [11] = {route = "HEADSHUNT01", signal = "SIDING04_SIGNAL", operation = "reverse"},
        [12] = {route = "SIDING05", signal = "HEADSHUNT01_SIGNAL", operation = "forward"},
        [13] = {route = "SHUNT01", signal = "SIDING05_SIGNAL", operation = "split_at_engine", split_count = 4},
        [14] = {route = nil, signal = nil, operation = "forward"},
        [15] = {route = nil, signal = nil, operation = "end"}
      }
    }
  elseif type == "loop_test_old" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "ALTSIDING01", signal = "SHUNT01_SIGNAL", operation = "forward"},
        [3] = {route = "SIDING01", signal = "ALTSIDING01_BACK", operation = "forward"},
        [4] = {route = "ALTSIDING01", signal = "SIDING01_SIGNAL", operation = "forward"},
        [5] = {route = "SIDING02", signal = "ALTSIDING01_BACK", operation = "forward"},
        [6] = {route = "SHUNT01", signal = "SIDING02_SIGNAL", operation = "forward"},
        [7] = {route = "SHUNT01", signal = nil, operation = "end"}
      }
    }
  elseif type == "test" then
    S.yards[yard] = {
      ["state"] = { status = "ready", current = 1, train_length_count = 1 },
      ["actions"] = {
        [1] = {route = "SHUNT01", signal = nil, operation = "start"},
        [2] = {route = "SIDING05", signal = "SHUNT01_SIGNAL", operation = "autocouple"},
        [3] = {route = "ALTSIDING01", signal = "SHUNT01_SIGNAL", operation = "forward"},
        [4] = {route = "SIDING01", signal = "ALTSIDING01_BACK", operation = "forward"},
        [5] = {route = "ALTSIDING01", signal = "SIDING01_SIGNAL", operation = "split_at_engine", split_count = 1},
        [6] = {route = "SIDING02", signal = "ALTSIDING01_BACK", operation = "forward"},
        [7] = {route = "SHUNT01", signal = "SIDING02_SIGNAL", operation = "forward"},
        [8] = {route = "SHUNT01", signal = nil, operation = "end"}
      }
    }
  else
    F.print("This type (" .. type .. ") is not defined")
  end
  F.yard_run(yard, section_id)
end

F.delete_train_info = function(train_id)
  if S.trains[train_id] then
    S.trains[train_id] = nil
    F.print("Deleted train id: " .. train_id)
  end
end

F.list_trains = function(number_of_displays)
  if S.trains then
    if number_of_displays == nil then number_of_displays = F.max_displays end
    F.clear_main_depot_displays()
    number_of_displays = number_of_displays + 1
    count_keys = 0
    trains_table = {}
    for k in pairs(S.trains) do
      table.insert(trains_table, k)
      count_keys = count_keys + 1
    end
    table.sort(trains_table)
    x = number_of_displays - count_keys
    for _, k in ipairs(trains_table) do
      if S.trains[k] then
        v = S.trains[k]
        if F.has_rc("LILSHUNTER", v["rc"]) or F.has_rc("LIL", v["rc"]) then
          F.delete_train_info(v["id"])
        else
          if v["ln"] == nil or v["ln"] == "" then
            line_number = ""
          else
            line_number = "| LN: [" .. v["ln"] .. "]"
          end
          if v["rc"] == nil or v["rc"] == "" then
            rc_display = ""
          else
            rc_list = v["rc"]
            rc_list_cleansed = ""
            rc_list_unknown = ""
            rc_list_table = {}
            if F.has_rc("ERSTAZI", rc_list) and F.has_rc("FREIGHT", rc_list) then
              rc_list_cleansed = "ERSTAZI FREIGHT |"
            else
              rc_list_cleansed = "NO E,F |"
            end
            for rc in rc_list:gmatch("[^%s]+") do
              if rc == "ERSTAZI" or rc == "FREIGHT" then
                -- leaving for future use
                do_nothing = true
              else
                if F.known_rcs[rc] ~= nil then
                  rc_list_cleansed = rc_list_cleansed .. " " .. rc
                else
                  rc_list_unknown = rc_list_unknown .. " " .. rc
                end
              end
            end
            rc_display = "| RC: " .. rc_list_cleansed
            if not F.isempty(rc_list_unknown) then
              rc_display = rc_display .. "| *URC*:" .. rc_list_unknown
            end
          end
          if v["cars_count"] == nil or v["cars_count"] == "" then
            cars_count_display = " Len: 0"
          else
            cars_count = tonumber(v["cars_count"])
            cars_count_display = " Len: " .. cars_count
          end
          message = " ID: " .. v["id"] .. cars_count_display .. rc_display ..  line_number
          if x > 0 then digiline_send("train_display" .. x, message) end
          F.print(x .. ": " .. message)
          x = x + 1
        end
      end
    end
  else
    F.print("no trains saved in S.trains")
  end
end

F.slow_train_down = function(id)
  result = atc_send_to_train(id, "B1")
  if result == false then
    F.print("Train ID " .. id .. " does not exist")
  else
    F.print("Train ID " .. id .. " is slowed down to B1")
  end
end

F.train_duration = function(type)
  if not atc_id then return end
  local now = os.date("%H:%M:%S")
  if F.isempty(type) then type = "start" end
  if not S.train_duration[atc_id] then
    S.train_duration[atc_id] = { ["train_id"] = atc_id, ["start"] = "", ["end"] = "", ["start_sec"] = "", ["end_sec"] = "", ["diff"] = {} }
  end
  if type == "start" then
    S.train_duration[atc_id]["end"] = nil
    S.train_duration[atc_id]["end_sec"] = nil
  end
  S.train_duration[atc_id][type] = now
  S.train_duration[atc_id][type .. "_sec"] = os.time()
  if
    S.train_duration[atc_id]["start_sec"] ~= nil
    and S.train_duration[atc_id]["start_sec"] ~= ""
    and S.train_duration[atc_id]["end_sec"] ~= nil
    and S.train_duration[atc_id]["end_sec"] ~= ""
    then
    if S.train_duration[atc_id]["diff"] == nil then S.train_duration[atc_id]["diff"] = {} end
    -- Returns the difference, in seconds, from time t1 to time t2 (where the times are values returned by os.time)
    difference_in_time = os.difftime(S.train_duration[atc_id]["end_sec"], S.train_duration[atc_id]["start_sec"])
    table.insert(S.train_duration[atc_id]["diff"], difference_in_time)
  end
end

F.train_info = function (passive_name, show_print)
  local timestart = ""
  local timeend = ""
  local time_message = ""
  local average_duration_message = ""
  if F.isempty(passive_name) or passive_name == "RESETALL" then
    train_id_message = "No Train"
    if passive_name == "RESETALL" then
      S.train_duration = {}
      -- Holding off on resetting the whole table of S.trains
      -- S.trains = {}
    end
  else
    timestart = S.train_duration[atc_id]["start"]
    timeend = S.train_duration[atc_id]["end"]
    train_id_message = "Last Train: " .. atc_id
  end
  if timestart == nil and timeend  == nil then
    time_message = "Current Time: |" .. os.date("%H:%M:%S")
  elseif timestart ~= nil and timeend == nil then
    time_message = "Start: |" .. timestart
  else
    time_message = "Time: |" .. timestart .. " to " .. timeend
  end
  average_duration_message = "|AVG: " .. math.ceil(F.avg(S.train_duration[atc_id]["diff"])) .. "s"
  local lcd_message = "" ..
        train_id_message .. "|" ..
        time_message ..
        average_duration_message ..
        ""
  digiline_send("lcd", lcd_message)
  local message = lcd_message .. " | " .. time_message
  if show_print == true then
    F.print(message)
  end
end