#! /usr/bin/env python

# Greenbone Security Assistant
# $Id$
# Description: Utility to generate pot files from gsa xslt sheets
#
# Authors:
#  Benoit Allard <benoit.allard@greenbone.net>
#
# Copyright:
#  Copyright (C) 2014 Greenbone Networks GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2,
# or, at your option, any later version as published by the Free
# Software Foundation
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.

# xgettext doesn't work for us:
#  - our patterns are inside ""
#  - the keyword contains a colon

import os
import polib
import re
import xml.sax.saxutils

gettext_re = re.compile(
    'gsa:i18n\s*\(\s*\'(?P<id>.+?)\'\s*(?:,\s*\'(?P<context>.*?)\'\s*)?'
    '(?:,\s*\'(?P<default>.*?)\'\s*)?\)')
ngettext_re = re.compile(
    'gsa:n-i18n\s*\(\s*\'(?P<id>.+?)\'\s*,\s*\'(?P<id_plural>.+?)\''
    '\s*,.+?(?:,\s*\'(?P<context>.*?)\'\s*)?(?:,\s*\'(?P<default>.*?)\''
    '\s*(?:,\s*\'(?P<default_plural>.*?)\'\s*)?)?\)')


def unescape(string):
    return xml.sax.saxutils.unescape(string,
                                     entities={'&quot;': '\"',
                                               '&amp;': '\''})


def process(filepath, po):
    print "Processing %s" % filepath

    with open(filepath) as xsl_file:
        content = xsl_file.read()

    parent_dir = os.path.os.path.dirname(filepath) + os.sep + os.pardir;
    filepath_short = os.path.relpath (filepath, parent_dir)

    for m in gettext_re.finditer(content):
        found_msgid = unescape(m.group('id'))
        found_msgctxt = m.group('context')
        if (found_msgctxt is not None) and (found_msgctxt != ""):
          found_msgctxt = unescape(found_msgctxt)
        else:
          found_msgctxt = None

        e = po.find(found_msgid, msgctxt=found_msgctxt)
        if e is None:
            e = polib.POEntry(
                msgid=found_msgid,
                msgctxt=found_msgctxt,
                occurrences=[(filepath_short,
                              content.count("\n", 0, m.start()) + 1)])
            if m.group('default') is not None:
                e.msgstr = unescape(m.group('default'))
                e.flags.append('fuzzy')
            po.append(e)
        else:
            e.occurrences.append(
                (filepath_short, content.count("\n", 0, m.start()) + 1))

    for m in ngettext_re.finditer(content):
        found_msgid = unescape(m.group('id'))
        found_msgid_plural = unescape(m.group('id_plural'))
        found_msgctxt = m.group('context')
        if (found_msgctxt is not None) and (found_msgctxt != ""):
          found_msgctxt = unescape(found_msgctxt)
        else:
          found_msgctxt = None

        e = po.find(found_msgid, msgctxt=found_msgctxt)
        if e is None:
            e = polib.POEntry(
                msgid=found_msgid,
                msgid_plural=found_msgid_plural,
                msgctxt=found_msgctxt,
                occurrences=[(filepath_short,
                              content.count("\n", 0, m.start()) + 1)])
            if m.group('default') is not None:
                e.msgstr = unescape(m.group('default'))
                e.flags.append('fuzzy')
                if unescape(m.group('default_plural')) is not None:
                    e.msgstr_plural[0] = unescape(m.group('default'))
                    e.msgstr_plural[1] = unescape(m.group('default_plural'))
                elif (e.msgid_plural is not None):
                    e.msgstr_plural[0] = ""
                    e.msgstr_plural[1] = ""
            elif (e.msgid_plural is not None):
                e.msgstr_plural[0] = ""
                e.msgstr_plural[1] = ""
            po.append(e)
        else:
            e.occurrences.append(
                (filepath_short, content.count("\n", 0, m.start()) + 1))


def main(xsldirpath, potfilepath=None):
    po = polib.POFile()
    po.metadata = {}

    for root, dirs, files in os.walk(xsldirpath):
        for filepath in files:
            if filepath.endswith('.xsl'):
                process(os.path.join(root, filepath), po)

    if potfilepath is None:
        potfilepath = os.path.join(xsldirpath, 'messages.pot')

    po.save(potfilepath)

if __name__ == "__main__":
    import sys
    if len(sys.argv) == 1:
        print "Usage: %s XSLIDIR [POTFILE]"
        sys.exit(1)
    main(*sys.argv[1:])
