#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`


    update-transifex-source-translations
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Update the transifex sources configuration file and push the source
'''

# Import python libs
import os
import sys
import time
import logging
import subprocess
import ConfigParser

try:
    import txclib.utils
except ImportError:
    sys.stdout.write(
        'The \'transifex-client\' library needs to be installed. '
        'Please execute one of \'pip install transifex-client\' or '
        '\'easy_install transifex-client\'\n'
    )
    sys.exit(1)

DOC_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))


def main():
    '''
    Run the update code
    '''
    os.chdir(DOC_DIR)

    sys.stdout.write('Extracting translatable strings....\n')
    try:
        subprocess.check_call(['make', 'gettext'])
    except subprocess.CalledProcessError as exc:
        sys.stdout.write('An error occurred while extracting the translation '
                         'strings: {0}\n'.format(exc))
        sys.exit(1)

    locale_dir = os.path.join(DOC_DIR, 'locale')
    pot_dir = os.path.join(DOC_DIR, '_build', 'locale')
    tx_root = txclib.utils.find_dot_tx()
    tx_config = os.path.join(tx_root, '.tx', 'config')

    if not tx_root:
        sys.stdout.write(
            'Unable to find the \'.tx/\' directory. Unable to continue\n'
        )
        sys.exit(1)

    # We do not want the txclib INFO or WARNING logging
    logging.getLogger('txclib').setLevel(logging.ERROR)

    sys.stdout.write('Gathering the translation template files...')
    sys.stdout.flush()
    entries = []
    for dirpath, dirnames, filenames in os.walk(pot_dir):
        for filename in filenames:
            pot_file = os.path.join(dirpath, filename)
            base, ext = os.path.splitext(pot_file)
            if ext != '.pot':
                continue
            resource_path = os.path.relpath(base, pot_dir)
            try:
                import babel.messages.pofile
                if not len(babel.messages.pofile.read_po(open(pot_file))):
                    # Empty pot file, continue
                    continue
            except ImportError:
                # No babel package, let's keep on going
                pass

            resource_name = resource_path.replace(
                '\\', '/').replace('/', '--').replace('.', '_')
            entries.append((resource_path, resource_name))
    sys.stdout.write('Done\n')

    # Let's load the resources already present in the configuration file
    cfg = ConfigParser.SafeConfigParser()
    cfg.read([tx_config])
    handled_resources = set(
        section for section in
        cfg.sections() if section.startswith('salt.')
    )

    sys.stdout.write('Updating the entries in \'.tx/config\'...\n')
    sys.stdout.flush()
    total_entries = len(entries)
    for idx, (resource_path, resource_name) in enumerate(sorted(entries)):
        sys.stdout.write(
            '[{0:>{pad}}/{1}] Updating resource for '
            '{resource_path}.pot ({resource_name})'.format(
                idx + 1,
                total_entries,
                pad=len(str(total_entries)),
                locale_dir=locale_dir,
                resource_name=resource_name,
                resource_path=resource_path
            )
        )
        sys.stdout.flush()
        try:
            txclib.utils.exec_command(
                'set',
                '--auto-local -r salt.{resource_name} '
                '{locale_dir}/<lang>/LC_MESSAGES/{resource_path}.po '
                '--source-lang en '
                '--source-file {pot_dir}/{resource_path}.pot '
                '--source-name {resource_path}.rst '
                '--execute'.format(
                    resource_name=resource_name,
                    resource_path=resource_path,
                    locale_dir=locale_dir,
                    pot_dir=pot_dir.rstrip('/')
                ).split(),
                tx_root
            )
            sys.stdout.write('\n')
            if 'salt.{0}'.format(resource_name) in handled_resources:
                handled_resources.remove('salt.{0}'.format(resource_name))
        except Exception as err:
            sys.stdout.write('An error occurred: {0}\n'.format(err))
        except KeyboardInterrupt:
            sys.stdout.write('\n')
            sys.exit(1)
        time.sleep(0.025)

    if handled_resources:
        non_handled_resources = len(handled_resources)
        sys.stdout.write(
            'Removing old resources from configuration and upstream'
            '(if possible)\n'
        )
        for idx, resource_name in enumerate(sorted(handled_resources)):
            sys.stdout.write(
                '[{0:>{pad}}/{1}] Removing resource {resource_name!r}'.format(
                    idx + 1,
                    non_handled_resources,
                    pad=len(str(non_handled_resources)),
                    resource_name=resource_name,
                )
            )
            sys.stdout.flush()
            try:
                txclib.utils.exec_command(
                    'delete',
                    ['-r', resource_name],
                    tx_root
                )
                handled_resources.remove(resource_name)
            except Exception as err:
                sys.stdout.write('An error occurred: {0}\n'.format(err))
            finally:
                if cfg.has_section(resource_name):
                    cfg.remove_section(resource_name)
            sys.stdout.write('\n')
            time.sleep(0.025)
        cfg.write(open(tx_config, 'w'))
        sys.stdout.write('\n')

    # Set the translations file type we're using
    txclib.utils.exec_command('set', ['-t', 'PO'], tx_root)
    time.sleep(0.025)

    if 'TRANSIFEX_NO_PUSH' not in os.environ:

        sys.stdout.write('\n')
        sys.stdout.write('Pushing translation template files...\n')
        for idx, (resource_path, resource_name) in enumerate(sorted(entries)):
            sys.stdout.write(
                '[{0:>{pad}}/{1}] Pushing resource for '
                '{resource_path}.pot ({resource_name})'.format(
                    idx + 1,
                    total_entries,
                    pad=len(str(total_entries)),
                    locale_dir=locale_dir,
                    resource_name=resource_name,
                    resource_path=resource_path
                )
            )
            sys.stdout.flush()
            try:
                txclib.utils.exec_command(
                    'push',
                    '--resource salt.{resource_name} '
                    '--source '
                    '--skip '
                    '--no-interactive'.format(
                        resource_name=resource_name,
                        resource_path=resource_path,
                        locale_dir=locale_dir
                    ).split(),
                    tx_root
                )
                sys.stdout.write('\n')
            except Exception as err:
                sys.stdout.write('An error occurred: {0}\n'.format(err))
            except KeyboardInterrupt:
                sys.stdout.write('\n')
                sys.exit(1)
            time.sleep(0.025)

    if handled_resources:
        sys.stdout.write('=' * 80)
        sys.stdout.write(
            '\nDon\'t forget to delete the following remote resources:\n')
        for resource_name in sorted(handled_resources):
            sys.stdout.write('    {0}\n'.format(resource_name))
        sys.stdout.write('=' * 80)

    sys.stdout.write('\nDONE\n')


if __name__ == '__main__':
    main()
