#!/usr/bin/python
# -*- mode: Python; coding: utf-8; -*-

# PO file consistency checker
# 
# Pedro Morais <morais@kde.org>
# José Nuno Pires <jncp@netcabo.pt>
# (c) Copyright 2003, 2004
# Distributable under the terms of the GPL - see COPYING

import sys
import os
import getopt
if not "/usr/share/gettext-lint" in sys.path:
    sys.path.append("/usr/share/gettext-lint")
from POFile import POFile
from Equivalent import Equivalent
from util import Output

def usage(code = -1):
    w = sys.stderr.write
    w('Usage: POFileConsistency [OPTION] <FILE>...\n')
    w('\n')
    w('Mandatory arguments to long options are mandatory '
      'for short options too.\n')
    w('\n')
    w('Options:\n')
    w('  -h, --help                 show this help\n')
    w('  -i, --interactive          interactive console mode\n')
    w('  -e, --equivalent=<file>    load an equivalences file\n')
    w('  -o, --only-empty           only check empty msgstrs\n')
    w('  -m, --match=<file>         only check files matching this name\n')
    w('  -r, --strip-chars=<chars>  remove this chars from the msgids\n')
    sys.exit(code)

try:
    opts, args = getopt.getopt(sys.argv[1:], "hioe:m:r:",
                               ["help", "interactive", "only-empty",
                                "equivalent=", "match=", "strip-chars="])
except getopt.GetoptError:
    usage()
interactive = 0
equivalentfiles = []
onlyempty = 0
match = None
strip = ''
for o, a in opts:
    if o in ("-h", "--help"): usage(0)
    if o in ("-i", "--interactive"): interactive = 1
    if o in ("-o", "--only-empty"): onlyempty = 1
    if o in ("-e", "--equivalent"): equivalentfiles.append(a)
    if o in ("-m", "--match"): match = a
    if o in ("-r", "--strip-chars"): strip = a
if len(args) < 1: usage()

equivalent = Equivalent()
for i in equivalentfiles:
    equivalent.parse(os.path.expandvars(os.path.expanduser(i)), strip)

map = {}
for filename in args:
    po = POFile(filename)
    po.ignoreFuzzy = 1
    if po.consistency(map, strip) == 0:
        sys.stderr.write('error parsing file %s\n' % filename)

def addIgnoreConsistency(po, e):
    header = po.data[0][3]
    header = header + ('X-POFile-IgnoreConsistency: %s\\n' % e)

    lines = po.prepare_replace(1)
    if lines != None:
        file = open(po.filename, 'w')
        po.execute_replace(lines, header, 1, file, breaknewlines = 1)
        file.close()
        po.data[0] = (po.data[0][0], po.data[0][1],
                      po.data[0][2], header, po.data[0][3])
        return 1
    return 0

def inconsistent(msgid, result, equivalent):
    if len(result) < 2: return 0
    if equivalent.check(msgid, result): return 0
    if onlyempty:
        ccc = 0
        for msgstr in result.keys():
            if not msgstr or not len(msgstr): ccc = 1
        if ccc == 0: return 0
    if match:
        ccc = 0
        for filenames in result.values():
            for filename, line in filenames:
                if filename.find(match) >= 0: ccc = 1
        if ccc == 0: return 0
    return 1

def consistency(map, equivalent):
    out = Output("po-file-consistency")
    for msgid, result in map.iteritems():
        if not inconsistent(msgid, result, equivalent): continue
        out.opentag('inconsistency')
        out.opentag('msgid', body = msgid, close = 1)
        for msgstr, filenames in result.iteritems():
            out.opentag('msgstr')
            out.opentag('content', body = msgstr, close = 1)
            for fx, message in filenames:
                out.opentag('filename', { 'message': str(message) },
                            body = fx, close = 1)
            out.closetag()
        out.closetag()
    out.finish()

def interactiveConsistency(map, equivalent):
    current = 0
    total = 0
    for msgid, result in map.iteritems():
        if inconsistent(msgid, result, equivalent): total = total + 1

    for msgid, result in map.iteritems():
        if not inconsistent(msgid, result, equivalent): continue
        current = current + 1
        print '*** msgid (%d/%d):\n%s' % (current, total, msgid)
        print
        c = 0
        for msgstr, filenames in result.iteritems():
            c = c + 1
            print '*** msgstr %d in' % c,
            for fx, message in filenames: print fx,
            print ':'
            print msgstr
        print
        addtofilemessage = ''
        if len(equivalentfiles):
            addtofilemessage = "'a' to add to ignore list, "
        x = raw_input("1 - %d to fix consistency, 0 to input text, %s\n"
                      "'l' to add to each file local ignore list, "
                      "other to continue: " % (c, addtofilemessage))
        if len(equivalentfiles) and x == 'a':
            print '+++ Adding to file %s' % equivalentfiles[0]
            print '+++'
            efile = open(equivalentfiles[0], 'a')
            print '+++ %s' % msgid
            efile.write('\n')
            efile.write('%s\n' % msgid)
            for msgstr, filenames in result.iteritems():
                print '+++ %s' % msgstr
                efile.write('%s\n' % msgstr)
            print
            efile.close()
            continue
        elif x == 'l':
            for msgstr, filenames in result.iteritems():
                for fx, message in filenames:
                    po = POFile(fx)
                    po.parse()
                    po.parseHeader()
                    if addIgnoreConsistency(po, msgid):
                        print '+++ Add ignore consistency to %s - %s' % (
                            fx, msgid)
                    else:
                        print '+++ Error adding ignore consistency to %s' % fx
            continue
        n = -1
        try:
            n = int(x)
        except:
            pass
        if n >= 0 and n <= c:
            newmsgstr = None
            if n == 0:
                newmsgstr = raw_input('Enter new message: ')
            else:
                c = 0
                for msgstr, filenames in result.iteritems():
                    c = c + 1
                    if c == n:
                        newmsgstr = msgstr
                        break
            c = 0
            for msgstr, filenames in result.iteritems():
                c = c + 1
                if c != n:
                    for fx, message in filenames:
                        print '+++ Fix consistency in %s,%d,%s' % (
                            fx, message, newmsgstr)
                        po = POFile(fx)
                        po.parse()
                        po.parseHeader()
                        lines = po.prepare_replace(message)
                        if lines != None:
                            file = open(fx, 'w')
                            po.execute_replace(lines, newmsgstr, 1, file)
                            file.close()
        print

if interactive:
    interactiveConsistency(map, equivalent)
else:
    consistency(map, equivalent)
