#!/usr/bin/env python

# Python-Loesung von Markus Korn

"""USAGE: footnotes.py [-a] [--test] [< input.txt]

    --test      Self-test using text SAMPLE in script source
    -a          Number footnotes in order of appearance in text
"""

SAMPLE = '''A great brown fox [13] jumped of a pile of lorem ipsum [4], [7]. He
met with a silver penguin, browsing the Linux Kernel Mailinglist [3]. They
debated other the question whether to start a C-program with "main (int argc,
char **argv)" or with "main (int argc, char *argv[])". Square brackets annoyed
them [9999]. Multiple references may exist to same targets [4].

@footnote:

[13] Al Fabetus: "On characters and animals", 1888, self published.
[4] Lorem Ipsum, <a href="http://en.wikipedia.org/wiki/Lorem_ipsum">Web Link</a>
[9999] Annoying Link.
[7] B. Fox: "More on Blind Text".
[3] Linux Kernel Maintainers: LKML
'''
import re, sys, operator
        
TEXT, FOOTNOTE = 0, re.MULTILINE
        
def sortdict_bykey(dct):
    x = sorted(dct.keys())
    for i in x:
        yield dct[i]

class SortedItems(object):
    def __init__(self, mode, part, nr_map=None):
        self.mode = mode
        self.part = part
        self.map = nr_map or {}
        self.count = 0
        
    def __call__(self, match):
        x = int(match.group(1))
        try:
            return "[%s]" %self.map[x]
        except KeyError:
            if not self.mode and self.part == TEXT:
                return "[0]"
            self.count += 1
            self.map[x] = self.count
            return "[%s]" %self.count
            
def sort_part(part, text, nr_map, mode):
    sort_func = SortedItems(mode, part, nr_map or None)
    r = re.compile(r"%s\[(\d+)\]" %(part and "^" or ""), part)
    if nr_map is None or part == TEXT:
        return r.sub(sort_func, text), sort_func.map
    elif part == FOOTNOTE:
        cache = {}
        for line in text.splitlines():
            nr, t = re.match(r"^\[(\d+)\](.*)", line).groups()
            neu = nr_map[int(nr)]
            cache[neu] = "[%s]%s" %(neu, t)
        return "\n".join(sortdict_bykey(cache)), nr_map   

def main(s, usebody=False):
    RE_FOOTSPLIT = re.compile(r'(\n*@footnote:[^\[]*)', re.MULTILINE)
    FOOTSPLIT = RE_FOOTSPLIT.search(s).group(1)
    body, footnote = s.split(FOOTSPLIT)
    if usebody:
        body, nr_map = sort_part(TEXT, body, None, usebody)
        footnote, _ = sort_part(FOOTNOTE, footnote, nr_map, usebody)
    else:
        footnote, nr_map = sort_part(FOOTNOTE, footnote, None, usebody)
        body, _ = sort_part(TEXT, body, nr_map, usebody)
    return body + FOOTSPLIT + footnote.rstrip("\n")

if __name__ == '__main__':
    if '--test' in sys.argv[1:]:
        print main(SAMPLE, usebody='-a' in sys.argv[1:])
    else:
        print main(sys.stdin.read(), usebody='-a' in sys.argv[1:])
