#!/usr/bin/env python

import os, sys
import codecs
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), '..', '..', 'libs', 'python', 'bongo', 'external'))
import simplejson
from optparse import OptionParser

class POParser(object):
        """ parse a .po file extracting msgids and msgstrs
        
        This class was found in a program with the following copyright. The
        URL was <http://mail.python.org/pipermail/mailman-i18n/2002-May/000521.html>
        
        transcheck - (c) 2002 by Simone Piunno <pioppo@ferrara.linux.it>
        
        This program is free software; you can redistribute it and/or modify it
        under the terms of the version 2.0 of the GNU General Public License as
        published by the Free Software Foundation."""
        
        def __init__(self, filename=""):
                self.status = 0
                self.files = []
                self.msgid = ""
                self.msgstr = ""
                self.line = 1
                self.f = None
                self.esc = { "n": "\n", "r": "\r", "t": "\t" }
                if filename:
                        self.open(filename)

        def open(self, filename):
                self.f = codecs.open(filename, "r", "utf-8", "strict")

        def close(self):
                self.f.close()

        def readline(self, fh):
                """ doing fh.readline() and then fh.read(1) fails for me
                    on python 2.5.1 :( So, this is a version of readline()
                    written as a series of read(1) calls. Lame, I know.
                """
                result = ""
                while 1:
                        char = fh.read(1)
                        if char == "\r":
                                pass
                        elif char == "\n":
                                return result
                        else:
                                result += char

        def parse(self):
                """States table for the finite-states-machine parser:
                        0  idle
                        1  filename-or-comment
                        2  msgid
                        3  msgstr
                        4  end
                """
                # each time we can safely re-initialize those vars
                self.files = []
                self.msgid = ""
                self.msgstr = ""

                # can't continue if status == 4, this is a dead status
                if self.status == 4:
                        return 0

                while 1:
                        # continue scanning, char-by-char
                        c = self.f.read(1)
                        if not c:
                                # EOF -> maybe we have a msgstr to save?
                                self.status = 4
                                if self.msgstr:
                                        return 1
                                else:
                                        return 0

                        # keep the line count up-to-date
                        if c == "\n": 
                                self.line += 1

                        # a pound was detected the previous char... 
                        if self.status == 1:
                                if c == ":": 
                                        # was a line of filenames
                                        row = self.readline(self.f)
                                        self.files += row.split()
                                        self.line += 1
                                elif c == "\n":
                                        # was a single pount on the line
                                        pass
                                else:
                                        # was a comment... discard
                                        self.readline(self.f)
                                        self.line += 1
                                # in every case, we switch to idle status
                                self.status = 0;
                                continue

                        # in idle status we search for a '#' or for a 'm'
                        if self.status == 0:
                                if   c == "#": 
                                        # this could be a comment or a filename
                                        self.status = 1;
                                        continue
                                elif c == "m": 
                                        # this should be a msgid start...
                                        s = self.f.read(4)
                                        assert s == "sgid"
                                        # so now we search for a '"'
                                        self.status = 2
                                        continue
                                # in idle only those other chars are possibile
                                assert c in [ "\n", " ", "\t" ]

                        # searching for the msgid string
                        if self.status == 2:
                                if c == "\n":
                                        # a double LF is not possible here
                                        c = self.f.read(1)
                                        assert c != "\n"
                                if c == "\"":
                                        # ok, this is the start of the string,
                                        # now search for the end
                                        while 1:
                                                c = self.f.read(1)
                                                if not c:
                                                        # EOF, bailout
                                                        self.status = 4
                                                        return 0
                                                if c == "\\":
                                                        # a quoted char...
                                                        c = self.f.read(1)
                                                        if self.esc.has_key(c):
                                                                self.msgid += self.esc[c]
                                                        else:
                                                                self.msgid += c
                                                        continue
                                                if c == "\"":
                                                        # end of string found
                                                        break
                                                # a normal char, add it 
                                                self.msgid += c
                                if c == "m":
                                        # this should be a msgstr identifier
                                        s = self.f.read(5)
                                        assert s == "sgstr"
                                        # ok, now search for the msgstr string
                                        self.status = 3

                        # searching for the msgstr string
                        if self.status == 3:
                                if c == "\n":
                                        # a double LF is the end of the msgstr!
                                        c = self.f.read(1)
                                        if c == "\n":
                                                # ok, time to go idle and return
                                                self.status = 0
                                                self.line += 1
                                                return 1
                                if c == "\"":
                                        # start of string found
                                        while 1:
                                                c = self.f.read(1)
                                                if not c:
                                                        # EOF, bail out
                                                        self.status = 4
                                                        return 1
                                                if c == "\\":
                                                        # a quoted char...
                                                        c = self.f.read(1)
                                                        if self.esc.has_key(c):
                                                                self.msgid += self.esc[c]
                                                        else:
                                                                self.msgid += c
                                                        continue
                                                if c == "\"":
                                                        # end of string
                                                        break
                                                # a normal char, add it
                                                self.msgstr += c


if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option("-p", "--pofile", dest="pofile", help="Path to PO file", metavar="FILE")
    parser.add_option("-o", "--output", dest="outfile", help="Output file. If none given, stdout is used", metavar="FILE")
    parser.add_option("-e", "--en", dest="en", action="store_true", help="Provide English, and therefore no, translation")
    (options, args) = parser.parse_args()

    if not options.pofile:
        print "You must specifiy an input PO file."
        sys.exit(1)

    po = POParser(options.pofile)
    output = {}

    # Skip the first line containing the pofile info like Last-Translator:
    po.parse()

    if options.en:
        while po.parse():
            output[po.msgid] = po.msgid
    else:
        while po.parse():
            output[po.msgid] = po.msgstr

    po.close()

    json = simplejson.dumps(output)

    if options.outfile:
        file = codecs.open(options.outfile, "w", "utf-8")
        file.write(json)
        file.close
    else:
        print json
