#!/usr/bin/env python

# Copyright (C) 2005 Osmo Salomaa
#
# This file is part of Gaupol.
#
# Gaupol is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Gaupol 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 Gaupol; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


"""
Translation related tasks for Gaupol.

Tasks handled by this script:
* Creating a new .po file
* Updating an existing .po file
* Compiling .mo files

Needed executables in path:
* intltool-extract
* msgfmt
* msginit
* msgmerge
* xgettext

Translatable strings are extracted from Glade XML files and Python source
code files.
"""


import glob
import optparse
import os
import sys


# Directories
SOURCE_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))
GLADE_DIR  = os.path.join(SOURCE_DIR, 'data'  , 'glade')
LIB_DIR    = os.path.join(SOURCE_DIR, 'lib'            )
LOCALE_DIR = os.path.join(SOURCE_DIR, 'locale'         )
PO_DIR     = os.path.join(SOURCE_DIR, 'po'             )

# Files
POT_PATH = os.path.join(PO_DIR, 'gaupol.pot')

# Paths of the C header files created from the Glade XML files and the Python
# source code files.
h_paths  = []
py_paths = []


def title_print(text):
    """Print a message that stands out from rest of the output."""

    print '** %s' % text

def compile_mo(lang):
    """Compile a .mo file for language lang."""

    for lang in get_languages(lang):

        title_print('Compiling a .mo file for language "%s"...' % lang)

        po_path = os.path.join(PO_DIR, '%s.po' % lang)
        mo_dir  = os.path.join(LOCALE_DIR, lang, 'LC_MESSAGES')
        mo_path = os.path.join(mo_dir, 'gaupol.mo')

        if not os.path.isdir(mo_dir):
            os.makedirs(mo_dir)

        os.system('msgfmt -cv %s -o %s' % (po_path, mo_path))

def create_po(lang):
    """Create a .po file for a new language lang."""

    po_path = os.path.join(PO_DIR, '%s.po' % lang)

    if os.path.isfile(po_path):
        print '.po file for language "%s" already exists.' % lang
        print 'Use the "-u" option to update the existing file.'
        raise SystemExit(1)

    title_print('Creating a .po file for language "%s"...' % lang)

    os.system('msginit -l %s -i %s -o %s' % (lang, POT_PATH, po_path))

def create_pot():
    """Create a .pot file."""

    title_print('Extracting strings from Glade XML files...')

    # Extract strings from Glade XML files to C header files.
    for (dirpath, dirnames, filenames) in os.walk(GLADE_DIR):
        os.chdir(dirpath)
        for filename in filenames:
            if not filename.endswith('.glade'):
                continue
            os.system('intltool-extract --type=gettext/glade %s' % filename)
            h_paths.append(os.path.join(dirpath, '%s.h' % filename))

    # Get a list of Python source code files.
    for (dirpath, dirnames, filenames) in os.walk(LIB_DIR):
        for filename in filenames:
            if filename.endswith('.py'):
                py_paths.append(os.path.join(dirpath, filename))

    # Create a .pot file from all source code files.
    title_print('Creating a .pot file from source files...')

    paths = h_paths + py_paths

    # Cut SOURCE_DIR out of paths to have only relevant parts of the paths
    # printed in the .po file.
    paths = list(path.replace(SOURCE_DIR, '.') for path in paths)

    os.chdir(SOURCE_DIR)
    os.system('xgettext -k_ -kN_ -c -o %s %s' % (POT_PATH, ' '.join(paths)))

def get_languages(lang):
    """
    Get a list of languages.

    lang = xx_YY or "all"
    """
    langs = []
    if lang == 'all':
        paths = glob.glob(os.path.join(PO_DIR, '*.po'))
        for path in paths:
            langs.append(os.path.basename(path)[:-3])
    else:
        langs.append(lang)

    return langs

def parse_options():
    """
    Parse given options and arguments.

    Return: options, arguments
    """
    description = \
        'Create or update Gaupol translation files. LANG should be a ' \
        'language code in either format "xx" or "xx_YY". Use "all" to ' \
        'process all languages found in the "po" directory.'
    usage = 'trantool [options]'
    formatter = optparse.IndentedHelpFormatter(2, 42, None, True)
    parser = optparse.OptionParser(
        description=description,
        formatter=formatter,
        usage=usage,
    )

    parser.add_option(
        '-p',
        '--create-po',
        action='store',
        type='string',
        metavar='LANG',
        dest='create_po',
        default='',
        help='create a new .po file'
    )
    parser.add_option(
        '-u',
        '--update-po',
        action='store',
        type='string',
        metavar='LANG',
        dest='update_po',
        default='',
        help='update an existing .po file'
    )
    parser.add_option(
        '-m',
        '--compile-mo',
        action='store',
        type='string',
        metavar='LANG',
        dest='compile_mo',
        default='',
        help='compile a .mo file'
    )

    return parser.parse_args(sys.argv)

def remove_temporary_files():
    """Remove temporary files created during operations."""

    title_print('Removing temporary files...')

    # .pot file
    #print POT_PATH.replace(SOURCE_DIR, '.')
    #os.remove(POT_PATH)

    # .h files
    for path in h_paths:
        print path.replace(SOURCE_DIR, '.')
        os.remove(path)

def update_po(lang):
    """Update an existing .po file with new strings."""

    for lang in get_languages(lang):
        title_print('Updating .po file for language "%s"...' % lang)
        po_path = os.path.join(PO_DIR, '%s.po' % lang)
        os.system('msgmerge -U %s %s' % (po_path, POT_PATH))


if __name__ == '__main__':

    opts, args = parse_options()

    if opts.create_po:
        create_pot()
        create_po(opts.create_po)
        remove_temporary_files()
    elif opts.update_po:
        create_pot()
        update_po(opts.update_po)
        remove_temporary_files()
    elif opts.compile_mo:
        compile_mo(opts.compile_mo)

    else:
        print 'Usage: trantool [options]'
        print 'See "./trantool --help" for details.'
