#!/usr/bin/env python
# -*- coding: utf8 -*-

"""
reorder footnotes

reads the input file line by line and writes every processed line direct to
stdout. So it is not a problem if the file is larger than the available
RAM. Footnotes are renumbered as they appear in the input file starting from 1.

The footnotes in the footnote section at the end of the file are stored
in memory, are renumbered and, after the last footnote is read,
printed out in sorted order.

usage:
$ python footnotes2.py infile.txt [ > outfile.txt]


"""

import re
import fileinput

MARKER = "@footnote:"
FNOTE = re.compile(r"\[(\d+)\]")


class FootnoteSorter(object):
	
	def __init__(self):
		self.in_footer = False
		self.fndict = {}  # footnote dict: key: old num, value: new num
		self.fnc = 0  # new footnote counter
		self.footnotes = {}  # holds all footnotes from the footnote-section:
							 # key: new footnote reference number
							 # value: footnote-text with the new reference number
		for line in fileinput.input():
			self.process_line(line)
		# write the footnotes sorted by reference to stdout:
		keys = self.footnotes.keys()
		keys.sort()
		for key in keys:
			print self.footnotes[key].strip()
		
	def process_line(self, line):
		if line.startswith(MARKER):
			self.in_footer = True
			print line.strip()
			return
		if not self.in_footer:
			fnlist = FNOTE.findall(line)  # fnl: footnotelist for this line
			for fn in fnlist:
				if fn not in self.fndict:  # it's a new "old" footnote number
					self.fnc += 1
					self.fndict[fn] = str(self.fnc)
				line = line.replace(fn, self.fndict[fn])
			print line.strip()
		else:
			# we are in the footer-section:
			# this lines are stored in memory and not direct send to stdout. 
			mo = FNOTE.match(line)
			if mo is not None:
				old_fn = mo.group(1)  # old footnote number
				try:
					new_fn = self.fndict[old_fn]  # new footnote number
				except KeyError:
					pass  # ignore
				else:
					self.footnotes[int(new_fn)] = line.replace(old_fn, new_fn)


if __name__ == "__main__":
	FootnoteSorter()
