#!/usr/bin/env python
# -*- coding: UTF-8 -*-

try:
    import fallback_import_paths
except:
    pass

import hashlib
import locale
import os
import optparse
import sys

from pology.catalog import Catalog
from pology.escape import escape_c, unescape_c
from pology.fsops import str_to_unicode
from pology.msgreport import warning_on_msg
from pology.report import warning, error


def main ():

    locale.setlocale(locale.LC_ALL, "")

    usage = (
        "\n"
        "  %prog extract FILE.pot FILE.csv [OPTIONS]\n"
        "  %prog inject FILE.csv FILE.po [OPTIONS]")
    desc = (
        "Simplistically extract a POT file into a monolanguage CSV file. "
        "Inject translated monolanguage CSV file into a PO file. "
        "Encoding of the CSV file is expected to be UTF-8 at all times, "
        "regardless of the PO file encoding.")
    ver = (
        u"%prog x1\n"
        u"Copyright © 2011, "
        u"Chusslove Illich (Часлав Илић) <caslav.ilic@gmx.net>")

    opars = optparse.OptionParser(usage=usage, description=desc, version=ver)
    _def_separator = "\t"
    opars.add_option(
        "-s", "--separator", metavar="CHAR",
        action="store", dest="separator", default=_def_separator,
        help="The character used to separate fields in the CSV file "
             "(default: %s)."
             % escape_c(_def_separator))
    opars.add_option(
        "-t", "--translator", metavar="'NAME <EMAIL>'",
        action="store", dest="translator", default=None,
        help="Name and email address of the translator, "
             "to update the PO header on injection.")

    options, free_args = opars.parse_args(str_to_unicode(sys.argv[1:]))
    if len(free_args) != 3:
        opars.print_usage()
        exit(1)

    mode = free_args[0]
    if mode == "extract":
        extract(free_args[1], free_args[2],
                separator=options.separator)
    elif mode == "inject":
        inject(free_args[1], free_args[2],
               separator=options.separator, translator=options.translator)
    else:
        error("Unknown operation mode '%s'." % mode)


def extract (potpath, csvpath, separator="\t"):

    cat = Catalog(potpath, monitored=False)
    enclines = []
    for msg in cat:
        if msg.msgid_plural is not None:
            warning_on_msg(
                "Extraction of plural messages not implemented yet, "
                "skipping.", msg, cat)
            continue
        msghex = get_msg_hex(msg)
        line = "%s%s\"%s\"" % (msghex, separator, escape_c(msg.msgid))
        encline = line.encode("utf8")
        enclines.append(encline)
    enclines.append("")

    csv = open(csvpath, "w")
    csv.writelines("\n".join(enclines))
    csv.close()


def inject (csvpath, popath, separator="\t", translator=None):

    # Read message hexes and translations from the CSV.
    csv = open(csvpath)
    trs_by_hex = {}
    lno = 0
    for encline in csv:
        lno += 1
        try:
            line = encline.decode("utf8")
        except:
            error("%s:%d: Cannot decode as UTF-8." % (csvpath, lno))
        try:
            flds = line.split(separator)
            msghex = flds[0].strip()
            msgstr = flds[1].strip()
            if not (msgstr.startswith("\"") and msgstr.endswith("\"")):
                raise StandardError
            msgstr = msgstr[1:-1]
            if not msgstr:
                raise StandardError
            msgstr = unescape_c(msgstr)
        except:
            # TODO: Be more specific.
            warning("%s:%d: Malformed line, skipping." % (csvpath, lno))
            continue
        trs_by_hex[msghex] = (msgstr, lno)

    # Inject translations into PO.
    cat = Catalog(popath)
    msgs_by_hex = {}
    for msg in cat:
        msghex = get_msg_hex(msg)
        msgstr, csvlno = trs_by_hex.get(msghex, [None, None])
        if msgstr is None:
            warning_on_msg("Not found in CSV file.", msg, cat)
            continue
        trs_by_hex.pop(msghex)
        if msgstr:
            msg.msgstr[0] = msgstr
            msg.unfuzzy()
    if translator is not None:
        cat.update_header(name=translator)
    cat.sync()

    extra_lnos = [x[1] for x in trs_by_hex.values()]
    if extra_lnos:
        warning("Some messages from CSV file do not exist in the PO file, "
                "at lines: %s."
                % ", ".join(map(str, sorted(extra_lnos))))


def get_msg_hex (msg):

    h = hashlib.md5()
    h.update(msg.key.encode("utf8"))
    msghex = h.hexdigest()
    return msghex


if __name__ == "__main__":
    main()
