# Copyright 2016 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import argparse
import subprocess
import tempfile
import shutil
import typing as T

parser = argparse.ArgumentParser()
parser.add_argument('command')
parser.add_argument('--build-dir', default='')
parser.add_argument('-i', '--input', default='')
parser.add_argument('-o', '--output', default='')
parser.add_argument('--itstool', default='itstool')
parser.add_argument('--its', action='append', default=[])
parser.add_argument('mo_files', nargs='+')


def run_join(build_dir: str, itstool: str, its_files: T.List[str], mo_files: T.List[str],
             in_fname: str, out_fname: str) -> int:
    if not mo_files:
        print('No mo files specified to use for translation.')
        return 1

    with tempfile.TemporaryDirectory(prefix=os.path.basename(in_fname), dir=build_dir) as tmp_dir:
        # copy mo files to have the right names so itstool can infer their locale
        locale_mo_files = []
        for mo_file in mo_files:
            if not os.path.exists(mo_file):
                print(f'Could not find mo file {mo_file}')
                return 1
            if not mo_file.endswith('.mo'):
                print(f'File is not a mo file: {mo_file}')
                return 1
            # determine locale of this mo file
            parts = mo_file.partition('LC_MESSAGES')
            if parts[0].endswith((os.sep, '/')):
                locale = os.path.basename(parts[0][:-1])
            else:
                locale = os.path.basename(parts[0])
            tmp_mo_fname = os.path.join(tmp_dir, locale + '.mo')
            shutil.copy(mo_file, tmp_mo_fname)
            locale_mo_files.append(tmp_mo_fname)

        cmd = [itstool]
        if its_files:
            for fname in its_files:
                cmd.extend(['-i', fname])
        cmd.extend(['-j', in_fname,
                    '-o', out_fname])
        cmd.extend(locale_mo_files)

        return subprocess.call(cmd)


def run(args: T.List[str]) -> int:
    options = parser.parse_args(args)
    command = options.command
    build_dir = os.environ.get('MESON_BUILD_ROOT', os.getcwd())
    if options.build_dir:
        build_dir = options.build_dir

    if command == 'join':
        return run_join(build_dir,
                        options.itstool,
                        options.its,
                        options.mo_files,
                        options.input,
                        options.output)
    else:
        print('Unknown subcommand.')
        return 1
