--[[  Misc Code
]]--
S.runarounds = {
	["M27_Breaker_Factory"] = {},
	["DJnc_4"] = {},
}
if event.init then
    local list_of_yards = {
        ["WOA"] = {},

    }
    S.yards = S.yards or list_of_yards
end

--[[  Utility Functions
]]--
F.indicator = function(indicator,set)
	if set ~= nil then
		if type(set) == string then
			setstate(indicator,set)
		else
			setstate(indicator,(set and "on") or "off")
		end
	end
	return (getstate(indicator) == "on") or false
end

F.dir = F.indicator -- legacy alias, to be updated to F.indicator

F.get_rc_safe = function()
	return get_rc() or ""
end

F.has_rc = function(query,rc_list) -- query = string, single entry
	if not atc_id then return false end
	if rc_list == "" or query == nil or query=="" then return false end
	if not rc_list then rc_list = F.get_rc_safe() end
	for word in rc_list:gmatch("[^%s]+") do
		if word == query then return true end
	end
	-- print(F.get_rc_safe())
	return false
end

F.has_rc_match = function(query,rc_list) -- query = pattern string, single entry
	if not atc_id then return false end
	if rc_list == "" or query == nil or query=="" then return false end
	if not rc_list then rc_list = F.get_rc_safe() end
	
	local rc = {}
	for v in rc_list:gmatch("("..query..")") do
		table.insert(rc,v)
	end
	
	if rc[1] == true then
		return true, rc
	else
		return nil
	end
end

F.add_rc = function(rc_list) -- rc_list = string or table, eg: {"rc1","rc2"} OR "rc1 rc2"
	if not atc_id then return false end
	if type(rc_list) == "table" then
		rc_list = table.concat(rc_list," ")
	end
	set_rc(F.get_rc_safe().." "..rc_list)
	-- print(F.get_rc_safe())
	return true
end

F.remove_rc = function(rc_list,arrow_mode) -- rc_list = string eg: "rc1 rc2 rc3" OR table eg: {"rc1","rc2","rc3"}
	-- Arrow Modes:
	-- true: with arrow direction
	-- false: against arrow direction
	-- nil: ignores arrow direction
	
	if not atc_id then return false end
	if not rc_list then return false end
	
	if (arrow_mode == nil) or (atc_arrow == arrow_mode) then		
		-- prep rc_list to useable format
		local rc_remove = {}
		if type(rc_list) == "string" then
			for word in rc_list:gmatch("[^%s]+") do
				rc_remove[word] = true
			end
		elseif type(rc_list) == "table" then
			for _,word in pairs(rc_list) do
				rc_remove[word] = true
			end
		end
		
		-- remove codes from train's rc
		local rc = F.get_rc_safe()
		local reinsert = {}
		for token in rc:gmatch("[^%s]+") do
			if not rc_remove[token] then
				table.insert(reinsert,token)
			end
		end
		-- insert new string to train's rc
		set_rc(table.concat(reinsert," "))
	end
	-- print(F.get_rc_safe())
	return reinsert
end

F.remove_rc_match = function(rc_list) -- rc_list = pattern string, single entry, eg: "rc_%d+"
	if not atc_id then return false end
	if not rc_list then return false end
	local rm = {}
	for v in F.get_rc_safe():gmatch("("..rc_list..")") do
		table.insert(rm,v)
	end
	F.remove_rc(rm)
	-- print(F.get_rc_safe())
	return rm
end

F.yard_road_count = function(yard,section_id,monitoring_light)
	if not S.yards[yard][section_id] then S.yards[yard][section_id] = {['car_count'] = 0} end
	
	local car_count = S.yards[yard][section_id].car_count
	
	if event.train then
		if atc_arrow then --arrow points into section, add to length
			car_count = car_count + train_length()
		else -- subtract from
			car_count = car_count - train_length()
		end
		
		if car_count > 0 then -- light = on
			setstate(monitoring_light,"on")
		else
			car_count = 0
			setstate(monitoring_light,"off")
		end
		
		S.yards[yard][section_id].car_count = car_count
	end
end



--[[  stats counter from subway/il_timetable
]]--
F.stat=function(line, init)
--statistics
-- init
if init then
reftrain = atc_id
a_tbt = 30
a_tbtmax = 30
a_rtt = 500
a_not = 0
c_not = 0
c_tbtmax = 0
time_lt = os.time()
time_rt=os.time()
end
if not a_tbtmax then a_tbtmax = 30 end
if not c_tbtmax then c_tbtmax = 0 end
--real code
if event.train then
local time = os.time()
c_not = c_not + 1
a_tbt = (a_tbt + (time - time_lt)) / 2
c_tbtmax = math.max(c_tbtmax, (time - time_lt))
if atc_id == reftrain then
  a_rtt = (a_rtt*0.2 + (time - time_rt)*0.8)
  a_not = c_not
  c_not = 0
  a_tbtmax = (a_tbtmax + c_tbtmax) / 2
  c_tbtmax = 0
end
  digiline_send("stats", "Stat: "..line..
    " NoT:"..a_not.."("..c_not..")"..
    " TbT:"..math.floor(a_tbt).."("..(time-time_lt)..")"..
    " Tmx:"..math.floor(a_tbtmax).."("..c_tbtmax..")"..
    " R:"..math.floor(a_rtt).."("..(time - time_rt)..")"
    )
time_lt = time
if atc_id == reftrain then
  time_rt = time
end
end
end

--[[ Custom Subway/Passenger Station Code
]]--
S.lines = {
	S23 = {
		termini = {
			N = "Arc",
			S = "Rew"
		},
		stations = {
			Rew = {
				name = "Redwood",
				doors = "L",
				next_station = {
					N = "Thc",
					S = false
				},
			},
			Thc = {
				name = "Tanh Cliffs",
				doors = "L",
				next_station = {
					N = "Noi",
					S = "Rew"
				},
			},
			Noi = {
				name = "No Idea",
				doors = "L",
				next_station = {
					N = "Lzf",
					S = "Thc"
				},
			},
			Lzf = {
				name = "Laza's Field",
				doors = "L",
				next_station = {
					N = "Bbh",
					S = "Noi"
				},
			},
			Bbh = {
				name = "Bamboo Hills",
				doors = "L",
				next_station = {
					N = "Arc",
					S = "Lzf"
				},
			},
			Arc = {
				name = "Arcadius",
				doors = "L",
				next_station = {
					N = false,
					S = "Bbh"
				},
			}
		},
		monitoring = {
			N = {},
			S = {}
		}
	},
	U21 = {
		termini = {
			E = "Tro",
			W = "Dbl"
		},
		stations = {
			Dbl = {
				name = "Dubulti",
				doors = "R",
				next_station = {
					E = "Pav",
					W = "Ghd"
				}
			},
			Pav = {
				name = "Pence Avenue",
				doors = "L",
				next_station = {
					E = "Ghd",
					W = "Dbl"
				}
			},
			Ghd = {
				name = "Greenhat Mountain",
				doors = "L",
				next_station = {
					E = "Acm",
					W = "Dbl"
				}
			},
			Acm = {
				name = "Acacia Mountains",
				doors = "L",
				next_station = {
					E = "Ghb",
					W = "Ghd"
				}
			},
			Ghb = {
				name = "Green Hill Beach",
				doors = "L",
				next_station = {
					E = "Ged",
					W = "Acm"
				}
			},
			Ged = {
				name = "Green Edge",
				doors = "L",
				next_station = {
					E = "Dri",
					W = "Ghb"
				}
			},
			Dri = {
				name = "Dry Island",
				doors = "L",
				next_station = {
					E = "Gcl",
					W = "Ged"
				}
			},
			Gcl = {
				name = "Green Cliffs",
				doors = "R",
				next_station = {
					E ="Sfs",
					W = "Dri"
				}
			},
			Sfs = {
				name = "South Forest",
				doors = "R",
				next_station = {
					E = "Jms",
					W = "Gcl"
				}
			},
			Jms = {
				name = "Jude Milhon Street",
				doors = "R",
				next_station = {
					E = "Bam",
					W = "Sfs"
				}
			},
			Bam = {
				name = "Bamboo Hills",
				doors = "R",
				next_station = {
					E = "Cli",
					W = "Jms"
				}
			},
			Cli = {
				name = "Clown Island",
				doors = "R",
				next_station = {
					E = "Wat",
					W = "Bam"
				}
			},
			Wat = {
				name = "Something in the Water",
				doors = "L",
				next_station = {
					E = "Duf",
					W = "Cli"
				}
			},
			Duf = {
				name = "Duff Rd",
				doors = "R",
				next_station = {
					E = "Tro",
					W = "Wat"
				}
			},
			Tro = {
				name = "Turtle Rock",
				doors = "L",
				next_station = {
					E = false,
					W = "Duf"
				},
			}
		},
		monitoring = {
			E = {},
			W = {},
			S = {},
			N = {}
		}
	}
}

F.arrive = function(stn_code,dir,line)
	S.lines[line].monitoring[dir][stn_code] = atc_id
    atc_send("B0 W O"..S.lines[line].stations[stn_code].doors)
    atc_set_text_inside("Arrived at:\n"..S.lines[line].stations[stn_code].name.."\n \nNext Station:\n"..S.lines[line].stations[S.lines[line].stations[stn_code].next_station[dir]].name)
end

F.depart = function(stn_code,dir,line)
	local pos = stn_code..dir
	local inside_text = "Next Stop:\n"..S.lines[line].stations[S.lines[line].stations[stn_code].next_station[dir]].name
	if can_set_route(pos,stn_code.."->"..S.lines[line].stations[stn_code].next_station[dir]) then
		set_route(pos,stn_code.."->"..S.lines[line].stations[stn_code].next_station[dir])
		atc_send("OC SM")
		S.lines[line].monitoring[dir][stn_code] = nil
		S.lines[line].monitoring[dir][S.lines[line].stations[stn_code].next_station[dir]] = atc_id
	else
		-- Wait another 5s before trying again
		inside_text = inside_text.."\nWaiting to depart..."
		interrupt(5, "depart")
	end
	atc_set_text_inside(inside_text)
end

F.set_desto = function(dir, line)
    atc_set_text_outside("LINE " .. line .."\n---> " .. S.lines[line].stations[S.lines[line].termini[dir]].name)
end

F.station = function(stn_code,dir,line)

-- temp until all SF LuaAtc tracks are changed-------------------------
	if line == nil or line == "1" then
		line = "U21"
	end
---------------------------------------------------------------------

	if event.train then
		F.arrive(stn_code,dir,line)
		interrupt(10,"depart")
	elseif event.int and event.msg=="depart" then
		F.depart(stn_code,dir,line)
	end
end

F.terminus = function(stn_code, newdir, line)
    if event.train then
		S.lines[line].monitoring[newdir][stn_code] = atc_id
		
		atc_send("B0 W R O"..S.lines[line].stations[stn_code].doors)
		atc_set_text_inside("Arrived at:\n"..S.lines[line].stations[stn_code].name.."\n \nNext Station:\n"..S.lines[line].stations[S.lines[line].stations[stn_code].next_station[newdir]].name)

        atc_set_text_outside("LINE " .. line .."\n---> " .. S.lines[line].stations[S.lines[line].termini[newdir]].name)
        interrupt(10, "depart")
    end
    if event.int and event.msg == "depart" then
        F.depart(stn_code, newdir,line)
    end
end