# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import absolute_import

'''
Replace localized parts of a packaged directory with data from a langpack
directory.
'''

import os
import mozpack.path as mozpath
from mozpack.packager.formats import (
    FlatFormatter,
    JarFormatter,
    OmniJarFormatter,
)
from mozpack.packager import (
    Component,
    SimplePackager,
    SimpleManifestSink,
)
from mozpack.files import (
    ComposedFinder,
    ManifestFile,
)
from mozpack.copier import (
    FileCopier,
    Jarrer,
)
from mozpack.chrome.manifest import (
    ManifestLocale,
    ManifestEntryWithRelPath,
    is_manifest,
    ManifestChrome,
    Manifest,
)
from mozpack.errors import errors
from mozpack.packager.unpack import UnpackFinder
from createprecomplete import generate_precomplete


class LocaleManifestFinder(object):
    def __init__(self, finder):
        entries = self.entries = []
        bases = self.bases = []

        class MockFormatter(object):
            def add_interfaces(self, path, content):
                pass

            def add(self, path, content):
                pass

            def add_manifest(self, entry):
                if entry.localized:
                    entries.append(entry)

            def add_base(self, base, addon=False):
                bases.append(base)

        # SimplePackager rejects "manifest foo.manifest" entries with
        # additional flags (such as "manifest foo.manifest application=bar").
        # Those type of entries are used by language packs to work as addons,
        # but are not necessary for the purpose of l10n repacking. So we wrap
        # the finder in order to remove those entries.
        class WrapFinder(object):
            def __init__(self, finder):
                self._finder = finder

            def find(self, pattern):
                for p, f in self._finder.find(pattern):
                    if isinstance(f, ManifestFile):
                        unwanted = [
                            e for e in f._entries
                            if isinstance(e, Manifest) and e.flags
                        ]
                        if unwanted:
                            f = ManifestFile(
                                f._base,
                                [e for e in f._entries if e not in unwanted])
                    yield p, f

        sink = SimpleManifestSink(WrapFinder(finder), MockFormatter())
        sink.add(Component(''), '*')
        sink.close(False)

        # Find unique locales used in these manifest entries.
        self.locales = list(set(e.id for e in self.entries
                                if isinstance(e, ManifestLocale)))


def _repack(app_finder, l10n_finder, copier, formatter, non_chrome=set()):
    app = LocaleManifestFinder(app_finder)
    l10n = LocaleManifestFinder(l10n_finder)

    # The code further below assumes there's only one locale replaced with
    # another one.
    if len(app.locales) > 1 or len(l10n.locales) > 1:
        errors.fatal("Multiple locales aren't supported")
    locale = app.locales[0]
    l10n_locale = l10n.locales[0]

    # For each base directory, store what path a locale chrome package name
    # corresponds to.
    # e.g., for the following entry under app/chrome:
    #     locale foo en-US path/to/files
    # keep track that the locale path for foo in app is
    # app/chrome/path/to/files.
    l10n_paths = {}
    for e in l10n.entries:
        if isinstance(e, ManifestChrome):
            base = mozpath.basedir(e.path, app.bases)
            l10n_paths.setdefault(base, {})
            l10n_paths[base][e.name] = e.path

    # For chrome and non chrome files or directories, store what langpack path
    # corresponds to a package path.
    paths = {}
    for e in app.entries:
        if isinstance(e, ManifestEntryWithRelPath):
            base = mozpath.basedir(e.path, app.bases)
            if base not in l10n_paths:
                errors.fatal("Locale doesn't contain %s/" % base)
                # Allow errors to accumulate
                continue
            if e.name not in l10n_paths[base]:
                errors.fatal("Locale doesn't have a manifest entry for '%s'" %
                    e.name)
                # Allow errors to accumulate
                continue
            paths[e.path] = l10n_paths[base][e.name]

    for pattern in non_chrome:
        for base in app.bases:
            path = mozpath.join(base, pattern)
            left = set(p for p, f in app_finder.find(path))
            right = set(p for p, f in l10n_finder.find(path))
            for p in right:
                paths[p] = p
            for p in left - right:
                paths[p] = None

    # Create a new package, with non localized bits coming from the original
    # package, and localized bits coming from the langpack.
    packager = SimplePackager(formatter)
    for p, f in app_finder:
        if is_manifest(p):
            # Remove localized manifest entries.
            for e in [e for e in f if e.localized]:
                f.remove(e)
        # If the path is one that needs a locale replacement, use the
        # corresponding file from the langpack.
        path = None
        if p in paths:
            path = paths[p]
            if not path:
                continue
        else:
            base = mozpath.basedir(p, paths.keys())
            if base:
                subpath = mozpath.relpath(p, base)
                path = mozpath.normpath(mozpath.join(paths[base],
                                                               subpath))
        if path:
            files = [f for p, f in l10n_finder.find(path)]
            if not len(files):
                if base not in non_chrome:
                    errors.error("Missing file: %s" %
                                 os.path.join(l10n_finder.base, path))
            else:
                packager.add(path, files[0])
        else:
            packager.add(p, f)

    # Add localized manifest entries from the langpack.
    l10n_manifests = []
    for base in set(e.base for e in l10n.entries):
        m = ManifestFile(base, [e for e in l10n.entries if e.base == base])
        path = mozpath.join(base, 'chrome.%s.manifest' % l10n_locale)
        l10n_manifests.append((path, m))
    bases = packager.get_bases()
    for path, m in l10n_manifests:
        base = mozpath.basedir(path, bases)
        packager.add(path, m)
        # Add a "manifest $path" entry in the top manifest under that base.
        m = ManifestFile(base)
        m.add(Manifest(base, mozpath.relpath(path, base)))
        packager.add(mozpath.join(base, 'chrome.manifest'), m)

    packager.close()

    # Add any remaining non chrome files.
    for pattern in non_chrome:
        for base in bases:
            for p, f in l10n_finder.find(mozpath.join(base, pattern)):
                if not formatter.contains(p):
                    formatter.add(p, f)

    # Transplant jar preloading information.
    for path, log in app_finder.jarlogs.iteritems():
        assert isinstance(copier[path], Jarrer)
        copier[path].preload([l.replace(locale, l10n_locale) for l in log])


def repack(source, l10n, extra_l10n={}, non_resources=[], non_chrome=set()):
    '''
    Replace localized data from the `source` directory with localized data
    from `l10n` and `extra_l10n`.

    The `source` argument points to a directory containing a packaged
    application (in omnijar, jar or flat form).
    The `l10n` argument points to a directory containing the main localized
    data (usually in the form of a language pack addon) to use to replace
    in the packaged application.
    The `extra_l10n` argument contains a dict associating relative paths in
    the source to separate directories containing localized data for them.
    This can be used to point at different language pack addons for different
    parts of the package application.
    The `non_resources` argument gives a list of relative paths in the source
    that should not be added in an omnijar in case the packaged application
    is in that format.
    The `non_chrome` argument gives a list of file/directory patterns for
    localized files that are not listed in a chrome.manifest.
    '''
    app_finder = UnpackFinder(source)
    l10n_finder = UnpackFinder(l10n)
    if extra_l10n:
        finders = {
            '': l10n_finder,
        }
        for base, path in extra_l10n.iteritems():
            finders[base] = UnpackFinder(path)
        l10n_finder = ComposedFinder(finders)
    copier = FileCopier()
    if app_finder.kind == 'flat':
        formatter = FlatFormatter(copier)
    elif app_finder.kind == 'jar':
        formatter = JarFormatter(copier, optimize=app_finder.optimizedjars)
    elif app_finder.kind == 'omni':
        formatter = OmniJarFormatter(copier, app_finder.omnijar,
                                     optimize=app_finder.optimizedjars,
                                     non_resources=non_resources)

    with errors.accumulate():
        _repack(app_finder, l10n_finder, copier, formatter, non_chrome)
    copier.copy(source, skip_if_older=False)
    generate_precomplete(source)
