# 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/.

'''jarmaker.py provides a python class to package up chrome content by
processing jar.mn files.

See the documentation for jar.mn on MDC for further details on the format.
'''

from __future__ import absolute_import

import sys
import os
import errno
import re
import logging
from time import localtime
from MozZipFile import ZipFile
from cStringIO import StringIO
from collections import defaultdict

from mozbuild.preprocessor import Preprocessor
from mozbuild.action.buildlist import addEntriesToListFile
from mozpack.files import FileFinder
import mozpack.path as mozpath
if sys.platform == 'win32':
    from ctypes import windll, WinError
    CreateHardLink = windll.kernel32.CreateHardLinkA

__all__ = ['JarMaker']


class ZipEntry(object):
    '''Helper class for jar output.

      This class defines a simple file-like object for a zipfile.ZipEntry
      so that we can consecutively write to it and then close it.
      This methods hooks into ZipFile.writestr on close().
      '''

    def __init__(self, name, zipfile):
        self._zipfile = zipfile
        self._name = name
        self._inner = StringIO()

    def write(self, content):
        '''Append the given content to this zip entry'''

        self._inner.write(content)
        return

    def close(self):
        '''The close method writes the content back to the zip file.'''

        self._zipfile.writestr(self._name, self._inner.getvalue())


def getModTime(aPath):
    if not os.path.isfile(aPath):
        return 0
    mtime = os.stat(aPath).st_mtime
    return localtime(mtime)


class JarManifestEntry(object):
    def __init__(self, output, source, is_locale=False, preprocess=False,
                 overwrite=False):
        self.output = output
        self.source = source
        self.is_locale = is_locale
        self.preprocess = preprocess
        self.overwrite = overwrite


class JarInfo(object):
    def __init__(self, base_or_jarinfo, name=None):
        if name is None:
            assert isinstance(base_or_jarinfo, JarInfo)
            self.base = base_or_jarinfo.base
            self.name = base_or_jarinfo.name
        else:
            assert not isinstance(base_or_jarinfo, JarInfo)
            self.base = base_or_jarinfo or ''
            self.name = name
            # For compatibility with existing jar.mn files, if there is no
            # base, the jar name is under chrome/
            if not self.base:
                self.name = mozpath.join('chrome', self.name)
        self.relativesrcdir = None
        self.chrome_manifests = []
        self.entries = []


class JarManifestParser(object):

    ignore = re.compile('\s*(\#.*)?$')
    jarline = re.compile('''
        (?:
            (?:\[(?P<base>[\w\d.\-\_\\\/{}@]+)\]\s*)? # optional [base/path]
            (?P<jarfile>[\w\d.\-\_\\\/{}]+).jar\:    # filename.jar:
        |
            (?:\s*(\#.*)?)                           # comment
        )\s*$                                        # whitespaces
        ''', re.VERBOSE)
    relsrcline = re.compile('relativesrcdir\s+(?P<relativesrcdir>.+?):')
    regline = re.compile('\%\s+(.*)$')
    entryre = '(?P<optPreprocess>\*)?(?P<optOverwrite>\+?)\s+'
    entryline = re.compile(entryre
                           + '(?P<output>[\w\d.\-\_\\\/\+\@]+)\s*(\((?P<locale>\%?)(?P<source>[\w\d.\-\_\\\/\@\*]+)\))?\s*$'
                           )

    def __init__(self):
        self._current_jar = None
        self._jars = []

    def write(self, line):
        # A Preprocessor instance feeds the parser through calls to this method.

        # Ignore comments and empty lines
        if self.ignore.match(line):
            return

        # A jar manifest file can declare several different sections, each of
        # which applies to a given "jar file". Each of those sections starts
        # with "<name>.jar:", in which case the path is assumed relative to
        # a "chrome" directory, or "[<base/path>] <subpath/name>.jar:", where
        # a base directory is given (usually pointing at the root of the
        # application or addon) and the jar path is given relative to the base
        # directory.
        if self._current_jar is None:
            m = self.jarline.match(line)
            if not m:
                raise RuntimeError(line)
            if m.group('jarfile'):
                self._current_jar = JarInfo(m.group('base'),
                                            m.group('jarfile'))
                self._jars.append(self._current_jar)
            return

        # Within each section, there can be three different types of entries:

        # - indications of the relative source directory we pretend to be in
        # when considering localization files, in the following form;
        # "relativesrcdir <path>:"
        m = self.relsrcline.match(line)
        if m:
            if self._current_jar.chrome_manifests or self._current_jar.entries:
                self._current_jar = JarInfo(self._current_jar)
                self._jars.append(self._current_jar)
            self._current_jar.relativesrcdir = m.group('relativesrcdir')
            return

        # - chrome manifest entries, prefixed with "%".
        m = self.regline.match(line)
        if m:
            rline = m.group(1)
            if rline not in self._current_jar.chrome_manifests:
                self._current_jar.chrome_manifests.append(rline)
            return

        # - entries indicating files to be part of the given jar. They are
        # formed thusly:
        #   "<dest_path>"
        # or
        #   "<dest_path> (<source_path>)"
        # The <dest_path> is where the file(s) will be put in the chrome jar.
        # The <source_path> is where the file(s) can be found in the source
        # directory. The <source_path> may start with a "%" for files part
        # of a localization directory, in which case the "%" counts as the
        # locale.
        # Each entry can be prefixed with "*" for preprocessing and "+" to
        # always overwrite the destination independently of file timestamps
        # (the usefulness of the latter is dubious in the modern days).
        m = self.entryline.match(line)
        if m:
            self._current_jar.entries.append(JarManifestEntry(
                m.group('output'),
                m.group('source') or mozpath.basename(m.group('output')),
                is_locale=bool(m.group('locale')),
                preprocess=bool(m.group('optPreprocess')),
                overwrite=bool(m.group('optOverwrite')),
            ))
            return

        self._current_jar = None
        self.write(line)

    def __iter__(self):
        return iter(self._jars)


class JarMaker(object):
    '''JarMaker reads jar.mn files and process those into jar files or
      flat directories, along with chrome.manifest files.
      '''

    def __init__(self, outputFormat='flat', useJarfileManifest=True,
        useChromeManifest=False):

        self.outputFormat = outputFormat
        self.useJarfileManifest = useJarfileManifest
        self.useChromeManifest = useChromeManifest
        self.pp = Preprocessor()
        self.topsourcedir = None
        self.sourcedirs = []
        self.localedirs = None
        self.l10nbase = None
        self.l10nmerge = None
        self.relativesrcdir = None
        self.rootManifestAppId = None

    def getCommandLineParser(self):
        '''Get a optparse.OptionParser for jarmaker.

        This OptionParser has the options for jarmaker as well as
        the options for the inner PreProcessor.
        '''

        # HACK, we need to unescape the string variables we get,
        # the perl versions didn't grok strings right

        p = self.pp.getCommandLineParser(unescapeDefines=True)
        p.add_option('-f', type='choice', default='jar',
            choices=('jar', 'flat', 'symlink'),
            help='fileformat used for output',
            metavar='[jar, flat, symlink]',
            )
        p.add_option('-v', action='store_true', dest='verbose',
                     help='verbose output')
        p.add_option('-q', action='store_false', dest='verbose',
                     help='verbose output')
        p.add_option('-e', action='store_true',
                     help='create chrome.manifest instead of jarfile.manifest'
                     )
        p.add_option('-s', type='string', action='append', default=[],
                     help='source directory')
        p.add_option('-t', type='string', help='top source directory')
        p.add_option('-c', '--l10n-src', type='string', action='append'
                     , help='localization directory')
        p.add_option('--l10n-base', type='string', action='store',
                     help='base directory to be used for localization (requires relativesrcdir)'
                     )
        p.add_option('--locale-mergedir', type='string', action='store'
                     ,
                     help='base directory to be used for l10n-merge (requires l10n-base and relativesrcdir)'
                     )
        p.add_option('--relativesrcdir', type='string',
                     help='relativesrcdir to be used for localization')
        p.add_option('-d', type='string', help='base directory')
        p.add_option('--root-manifest-entry-appid', type='string',
                     help='add an app id specific root chrome manifest entry.'
                     )
        return p

    def processIncludes(self, includes):
        '''Process given includes with the inner PreProcessor.

        Only use this for #defines, the includes shouldn't generate
        content.
        '''

        self.pp.out = StringIO()
        for inc in includes:
            self.pp.do_include(inc)
        includesvalue = self.pp.out.getvalue()
        if includesvalue:
            logging.info('WARNING: Includes produce non-empty output')
        self.pp.out = None

    def finalizeJar(self, jardir, jarbase, jarname, chromebasepath, register, doZip=True):
        '''Helper method to write out the chrome registration entries to
         jarfile.manifest or chrome.manifest, or both.

        The actual file processing is done in updateManifest.
        '''

        # rewrite the manifest, if entries given
        if not register:
            return

        chromeManifest = os.path.join(jardir, jarbase, 'chrome.manifest')

        if self.useJarfileManifest:
            self.updateManifest(os.path.join(jardir, jarbase,
                                             jarname + '.manifest'),
                                chromebasepath.format(''), register)
            if jarname != 'chrome':
                addEntriesToListFile(chromeManifest,
                                     ['manifest {0}.manifest'.format(jarname)])
        if self.useChromeManifest:
            chromebase = os.path.dirname(jarname) + '/'
            self.updateManifest(chromeManifest,
                                chromebasepath.format(chromebase), register)

        # If requested, add a root chrome manifest entry (assumed to be in the parent directory
        # of chromeManifest) with the application specific id. In cases where we're building
        # lang packs, the root manifest must know about application sub directories.

        if self.rootManifestAppId:
            rootChromeManifest = \
                os.path.join(os.path.normpath(os.path.dirname(chromeManifest)),
                             '..', 'chrome.manifest')
            rootChromeManifest = os.path.normpath(rootChromeManifest)
            chromeDir = \
                os.path.basename(os.path.dirname(os.path.normpath(chromeManifest)))
            logging.info("adding '%s' entry to root chrome manifest appid=%s"
                          % (chromeDir, self.rootManifestAppId))
            addEntriesToListFile(rootChromeManifest,
                                 ['manifest %s/chrome.manifest application=%s'
                                  % (chromeDir,
                                 self.rootManifestAppId)])

    def updateManifest(self, manifestPath, chromebasepath, register):
        '''updateManifest replaces the % in the chrome registration entries
        with the given chrome base path, and updates the given manifest file.
        '''
        myregister = dict.fromkeys(map(lambda s: s.replace('%',
            chromebasepath), register))
        addEntriesToListFile(manifestPath, myregister.iterkeys())

    def makeJar(self, infile, jardir):
        '''makeJar is the main entry point to JarMaker.

        It takes the input file, the output directory, the source dirs and the
        top source dir as argument, and optionally the l10n dirs.
        '''

        # making paths absolute, guess srcdir if file and add to sourcedirs
        _normpath = lambda p: os.path.normpath(os.path.abspath(p))
        self.topsourcedir = _normpath(self.topsourcedir)
        self.sourcedirs = [_normpath(p) for p in self.sourcedirs]
        if self.localedirs:
            self.localedirs = [_normpath(p) for p in self.localedirs]
        elif self.relativesrcdir:
            self.localedirs = \
                self.generateLocaleDirs(self.relativesrcdir)
        if isinstance(infile, basestring):
            logging.info('processing ' + infile)
            self.sourcedirs.append(_normpath(os.path.dirname(infile)))
        pp = self.pp.clone()
        pp.out = JarManifestParser()
        pp.do_include(infile)

        for info in pp.out:
            self.processJarSection(info, jardir)

    def generateLocaleDirs(self, relativesrcdir):
        if os.path.basename(relativesrcdir) == 'locales':
            # strip locales
            l10nrelsrcdir = os.path.dirname(relativesrcdir)
        else:
            l10nrelsrcdir = relativesrcdir
        locdirs = []

        # generate locales dirs, merge, l10nbase, en-US
        if self.l10nmerge:
            locdirs.append(os.path.join(self.l10nmerge, l10nrelsrcdir))
        if self.l10nbase:
            locdirs.append(os.path.join(self.l10nbase, l10nrelsrcdir))
        if self.l10nmerge or not self.l10nbase:
            # add en-US if we merge, or if it's not l10n
            locdirs.append(os.path.join(self.topsourcedir,
                           relativesrcdir, 'en-US'))
        return locdirs

    def processJarSection(self, jarinfo, jardir):
        '''Internal method called by makeJar to actually process a section
        of a jar.mn file.
        '''

        # chromebasepath is used for chrome registration manifests
        # {0} is getting replaced with chrome/ for chrome.manifest, and with
        # an empty string for jarfile.manifest

        chromebasepath = '{0}' + os.path.basename(jarinfo.name)
        if self.outputFormat == 'jar':
            chromebasepath = 'jar:' + chromebasepath + '.jar!'
        chromebasepath += '/'

        jarfile = os.path.join(jardir, jarinfo.base, jarinfo.name)
        jf = None
        if self.outputFormat == 'jar':
            # jar
            jarfilepath = jarfile + '.jar'
            try:
                os.makedirs(os.path.dirname(jarfilepath))
            except OSError, error:
                if error.errno != errno.EEXIST:
                    raise
            jf = ZipFile(jarfilepath, 'a', lock=True)
            outHelper = self.OutputHelper_jar(jf)
        else:
            outHelper = getattr(self, 'OutputHelper_'
                                + self.outputFormat)(jarfile)

        if jarinfo.relativesrcdir:
            self.localedirs = self.generateLocaleDirs(jarinfo.relativesrcdir)

        for e in jarinfo.entries:
            self._processEntryLine(e, outHelper, jf)

        self.finalizeJar(jardir, jarinfo.base, jarinfo.name, chromebasepath,
                         jarinfo.chrome_manifests)
        if jf is not None:
            jf.close()

    def _processEntryLine(self, e, outHelper, jf):
        out = e.output
        src = e.source

        # pick the right sourcedir -- l10n, topsrc or src

        if e.is_locale:
            src_base = self.localedirs
        elif src.startswith('/'):
            # path/in/jar/file_name.xul     (/path/in/sourcetree/file_name.xul)
            # refers to a path relative to topsourcedir, use that as base
            # and strip the leading '/'
            src_base = [self.topsourcedir]
            src = src[1:]
        else:
            # use srcdirs and the objdir (current working dir) for relative paths
            src_base = self.sourcedirs + [os.getcwd()]

        if '*' in src:
            def _prefix(s):
                for p in s.split('/'):
                    if '*' not in p:
                        yield p + '/'
            prefix = ''.join(_prefix(src))
            for _srcdir in src_base:
                finder = FileFinder(_srcdir, find_executables=False)
                for path, _ in finder.find(src):
                    e = JarManifestEntry(
                        mozpath.join(out, path[len(prefix):]),
                        path,
                        is_locale=e.is_locale,
                        preprocess=e.preprocess,
                        overwrite=e.overwrite
                    )
                    self._processEntryLine(e, outHelper, jf)
            return

        # check if the source file exists
        realsrc = None
        for _srcdir in src_base:
            if os.path.isfile(os.path.join(_srcdir, src)):
                realsrc = os.path.join(_srcdir, src)
                break
        if realsrc is None:
            if jf is not None:
                jf.close()
            raise RuntimeError('File "{0}" not found in {1}'.format(src,
                               ', '.join(src_base)))
        if e.preprocess:
            outf = outHelper.getOutput(out)
            inf = open(realsrc)
            pp = self.pp.clone()
            if src[-4:] == '.css':
                pp.setMarker('%')
            pp.out = outf
            pp.do_include(inf)
            pp.failUnused(realsrc)
            outf.close()
            inf.close()
            return

        # copy or symlink if newer or overwrite

        if e.overwrite or getModTime(realsrc) \
            > outHelper.getDestModTime(e.output):
            if self.outputFormat == 'symlink':
                outHelper.symlink(realsrc, out)
                return
            outf = outHelper.getOutput(out)

            # open in binary mode, this can be images etc

            inf = open(realsrc, 'rb')
            outf.write(inf.read())
            outf.close()
            inf.close()

    class OutputHelper_jar(object):
        '''Provide getDestModTime and getOutput for a given jarfile.'''

        def __init__(self, jarfile):
            self.jarfile = jarfile

        def getDestModTime(self, aPath):
            try:
                info = self.jarfile.getinfo(aPath)
                return info.date_time
            except:
                return 0

        def getOutput(self, name):
            return ZipEntry(name, self.jarfile)

    class OutputHelper_flat(object):
        '''Provide getDestModTime and getOutput for a given flat
        output directory. The helper method ensureDirFor is used by
        the symlink subclass.
        '''

        def __init__(self, basepath):
            self.basepath = basepath

        def getDestModTime(self, aPath):
            return getModTime(os.path.join(self.basepath, aPath))

        def getOutput(self, name):
            out = self.ensureDirFor(name)

            # remove previous link or file
            try:
                os.remove(out)
            except OSError, e:
                if e.errno != errno.ENOENT:
                    raise
            return open(out, 'wb')

        def ensureDirFor(self, name):
            out = os.path.join(self.basepath, name)
            outdir = os.path.dirname(out)
            if not os.path.isdir(outdir):
                try:
                    os.makedirs(outdir)
                except OSError, error:
                    if error.errno != errno.EEXIST:
                        raise
            return out

    class OutputHelper_symlink(OutputHelper_flat):
        '''Subclass of OutputHelper_flat that provides a helper for
        creating a symlink including creating the parent directories.
        '''

        def symlink(self, src, dest):
            out = self.ensureDirFor(dest)

            # remove previous link or file
            try:
                os.remove(out)
            except OSError, e:
                if e.errno != errno.ENOENT:
                    raise
            if sys.platform != 'win32':
                os.symlink(src, out)
            else:
                # On Win32, use ctypes to create a hardlink
                rv = CreateHardLink(out, src, None)
                if rv == 0:
                    raise WinError()


def main(args=None):
    args = args or sys.argv
    jm = JarMaker()
    p = jm.getCommandLineParser()
    (options, args) = p.parse_args(args)
    jm.processIncludes(options.I)
    jm.outputFormat = options.f
    jm.sourcedirs = options.s
    jm.topsourcedir = options.t
    if options.e:
        jm.useChromeManifest = True
        jm.useJarfileManifest = False
    if options.l10n_base:
        if not options.relativesrcdir:
            p.error('relativesrcdir required when using l10n-base')
        if options.l10n_src:
            p.error('both l10n-src and l10n-base are not supported')
        jm.l10nbase = options.l10n_base
        jm.relativesrcdir = options.relativesrcdir
        jm.l10nmerge = options.locale_mergedir
        if jm.l10nmerge and not os.path.isdir(jm.l10nmerge):
            logging.warning("WARNING: --locale-mergedir passed, but '%s' does not exist. "
                "Ignore this message if the locale is complete." % jm.l10nmerge)
    elif options.locale_mergedir:
        p.error('l10n-base required when using locale-mergedir')
    jm.localedirs = options.l10n_src
    if options.root_manifest_entry_appid:
        jm.rootManifestAppId = options.root_manifest_entry_appid
    noise = logging.INFO
    if options.verbose is not None:
        noise = options.verbose and logging.DEBUG or logging.WARN
    if sys.version_info[:2] > (2, 3):
        logging.basicConfig(format='%(message)s')
    else:
        logging.basicConfig()
    logging.getLogger().setLevel(noise)
    topsrc = options.t
    topsrc = os.path.normpath(os.path.abspath(topsrc))
    if not args:
        infile = sys.stdin
    else:
        (infile, ) = args
    jm.makeJar(infile, options.d)
