#!/usr/bin/python
# -*- coding: utf-8 -*-
# Generate indexes files for the Crep's chordbook compilation. This is
# a replacement for the original makeindex program written in C that
# produces an index file (.sbx) from a file generated by the latex
# compilation of the songbook (.sxd).
#
# Usage : songbook-makeindex.py src
#         src is the .sxd file generated by latex
#

import sys
import os.path
import glob
import re
from optparse import OptionParser
import title_sort
import locale

# Pattern set to ignore latex command in title prefix
keywordPattern = re.compile(r"^%(\w+)\s?(\w*)")
firstLetterPattern = re.compile(r"^(?:\{?\\\w+\}?)*[^\w]*(\w)")

class index:
    data = dict()
    keywords = dict()

    def filter(self, key):
        letter = firstLetterPattern.match(key).group(1)
        if re.match('\d',letter):
            letter = '0-9'
        return (letter.upper(), key)

    def keyword(self, key, word):
        if not self.keywords.has_key(key):
            self.keywords[key] = []
        self.keywords[key].append(word)

    def compileKeywords(self):
        pass

    def add(self, key, number, link):
        (first, key) = self.filter(key)
        if not self.data.has_key(first):
            self.data[first] = dict()
        if not self.data[first].has_key(key):
            self.data[first][key] = []
        self.data[first][key].append({'num':number, 'link':link})

    def refToStr(self, ref):
        if sys.version_info >= (2,6):
            return '\\hyperlink{{{0[link]}}}{{{0[num]}}}'.format(ref)
        else:
            return '\\hyperlink{%(link)s}{%(num)s}' % ref

    def entryToStr(self, key, entry):
        if sys.version_info >= (2,6):
            return '\\idxentry{{{0}}}{{{1}}}\n'.format(key, '\\\\'.join(map(self.refToStr, entry)))
        else:
            return '\\idxentry{%s}{%s}\n' % (key, '\\\\'.join(map(self.refToStr, entry)))

    def idxBlockToStr(self, letter, entries):
        str = '\\begin{idxblock}{'+letter+'}'+'\n'
        for key in sorted(entries.keys(), key=title_sort.sortkey):
            str += self.entryToStr(key, entries[key])
        str += '\\end{idxblock}'+'\n'
        return str

    def entriesToStr(self):
        str = ""
        for letter in sorted(self.data.keys()):
            str += self.idxBlockToStr(letter, self.data[letter])
        return str

def processSXDEntry(tab):
    return (tab[0], tab[1], tab[2])

def processSXD(filename):
    file = open(filename)
    data = []
    for line in file:
        data.append(line.strip())
    file.close()

    type = data[0]
    i = 1
    idx = index()
    while data[i].startswith('%'):
        keywords = keywordPattern.match(data[i]).groups()
        idx.keyword(keywords[0],keywords[1])
        i += 1
    idx.compileKeywords()
    for i in range(i,len(data),3):
        entry = processSXDEntry(data[i:i+3])
        idx.add(entry[0],entry[1],entry[2])
    return idx

def usage(exitCode=None):
    print "usage: songbook-makeindex.py [options] source"
    sys.exit(exitCode)

def main():
    locale.setlocale(locale.LC_ALL, '')
    usage = "usage: %prog [options] FILE"
    parser = OptionParser(usage)
    parser.add_option("-o", "--output", dest="filename",
                      help="write result into FILE", metavar="FILE")
    (options, args) = parser.parse_args()

    # Args processing
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    if not os.path.exists(args[0]):
        parser.error("inexistant input file")

    # Options processing
    if options.filename:
        output = open(options.filename,"w")
    else:
        output = sys.stdout

    # Actual processing
    idx = processSXD(args[0])
    output.write(idx.entriesToStr())

if __name__ == '__main__':
    main()