#!/usr/bin/env python3
import sys
from os import path
linesep = "\n"

if len(sys.argv) != 3 or not sys.argv[1] or not sys.argv[2]:
	print("Usage: coldstore.py <game_directory> <leaderboard_records.lua>")
	print("\t<game_directory>\t\tthe game directory where wads and luafiles reside. Usually at '$HOME/.srb2kart'.")
	print("\t<leaderboard_records.lua>\tthe output name for the records packed lua file. It will be saved within <game_directory>.")
	quit()

if not sys.argv[2].endswith(".lua"):
	print("{} must end with .lua".format(sys.argv[2]))
	quit()

game_dir = sys.argv[1]
leaderboard_txt = path.join(game_dir, "luafiles", "leaderboard.txt")
coldstore_txt = path.join(game_dir, "luafiles", "leaderboard.coldstore.txt")
records_lua = path.join(game_dir, sys.argv[2])

def ParseScore(score):
	# Map Name Skin Color Time Splits Flags Stat
	split = score.split("\t")

	checksum = ""
	if len(split) > 8:
		checksum = split[8]

	return {
		"map": split[0],
		"name": split[1],
		"skin": split[2],
		"color": split[3],
		"time": int(split[4]),
		"splits": split[5],
		"flags": int(split[6]),
		"stat": split[7],
		"checksum": checksum
	}

# Compare scores
def CompareScore(a, b):
	return a["time"] < b["time"]

F_SEP = 0xF
def SameScore(a, b):
	return a["name"] == b["name"] and a["checksum"] == b["checksum"] and (a["flags"] & F_SEP) == (b["flags"] & F_SEP)

def LoadRecordsFromFile(path):
	records = []
	try:
		with open(path, "r") as f:
			for line in f.readlines():
				line = line.strip()
				if line != "":
					records.append(ParseScore(line))
	except FileNotFoundError:
		pass

	return records

def AddScore(records, score):
	mapid = score["map"]
	mapTable = records.get(mapid) or []

	for i in range(len(mapTable)):
		scoreb = mapTable[i]
		if SameScore(score, scoreb):
			if CompareScore(score, scoreb):
				mapTable[i] = score
				records[mapid] = mapTable
			return
	mapTable.append(score)
	records[mapid] = mapTable

# load leaderboard.txt and coldstore.txt
recordsList = LoadRecordsFromFile(leaderboard_txt)
recordsList.extend(LoadRecordsFromFile(coldstore_txt))


# construct the map tables
records = {}
for score in recordsList:
	AddScore(records, score)

# convert records to flat list
recordsList = []
rejected = []
for mapTable in records.values():
	for score in mapTable:
		scoreStr = "\t".join([str(v) for v in list(score.values())])
		# only allow records with checksums
		if score["checksum"] != "":
			recordsList.append(scoreStr)
		else:
			rejected.append(scoreStr)

# truncate and write records to coldstore
with open(coldstore_txt, "w") as f:
	for score in recordsList:
			f.write(score + linesep)

luaA = """do
	local AddColdStore = lb_add_coldstore_record_string
	local records = {
"""
luaB = """	}
	for _, str in ipairs(records) do
		AddColdStore(str)
	end
end
"""
# pack the records.lua file
with open(records_lua, "w") as f:
	f.write(luaA)
	for score in recordsList:
		score = score.replace("\\", "\\\\")
		score = score.replace("\"", "\\\"")
		f.write("\t\t\"{}\",{}".format(score, linesep))
	f.write(luaB)

# truncate and rewrite rejected scores to leaderboard.txt
with open(leaderboard_txt, "w") as f:
	for score in rejected:
		f.write(score + linesep)