#!/usr/bin/env python3
# Copyright (C) 2014 Igalia S.L.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

from __future__ import print_function
from contextlib import closing

import argparse
import errno
import multiprocessing
import os
import re
import shutil
import subprocess
import tarfile


def enum(**enums):
    return type('Enum', (), enums)


class Rule(object):
    Result = enum(INCLUDE=1, EXCLUDE=2, NO_MATCH=3)

    def __init__(self, type, pattern):
        self.type = type
        self.original_pattern = pattern
        self.pattern = re.compile(pattern)

    def test(self, file):
        if not(self.pattern.search(file)):
            return Rule.Result.NO_MATCH
        return self.type


class Ruleset(object):
    _global_rules = None

    def __init__(self):
        # By default, accept all files.
        self.rules = [Rule(Rule.Result.INCLUDE, '.*')]

    @classmethod
    def global_rules(cls):
        if not cls._global_rules:
            cls._global_rules = Ruleset()
        return cls._global_rules

    @classmethod
    def add_global_rule(cls, rule):
        cls.global_rules().add_rule(rule)

    def add_rule(self, rule):
        self.rules.append(rule)

    def passes(self, file):
        allowed = False
        for rule in self.rules:
            result = rule.test(file)
            if result == Rule.Result.NO_MATCH:
                continue
            allowed = Rule.Result.INCLUDE == result
        return allowed


class File(object):
    def __init__(self, source_root, tarball_root):
        self.source_root = source_root
        self.tarball_root = tarball_root

    def should_skip_file(self, path):
        # Do not skip files explicitly added from the manifest.
        return False

    def get_files(self):
        yield (self.source_root, self.tarball_root)


class Directory(object):
    def __init__(self, source_root, tarball_root):
        self.source_root = source_root
        self.tarball_root = tarball_root
        self.rules = Ruleset()

        self.files_in_version_control = self.list_files_in_version_control()

    def add_rule(self, rule):
        self.rules.add_rule(rule)

    def get_tarball_path(self, filename):
        return filename.replace(self.source_root, self.tarball_root, 1)

    def list_files_in_version_control(self):
        # FIXME: Only git is supported for now.
        p = subprocess.Popen(['git', 'ls-tree', '-r', '--name-only', 'HEAD', self.source_root], stdout=subprocess.PIPE, text="ascii")
        out = p.communicate()[0]
        if not out:
            return []
        return frozenset(out.splitlines())

    def should_skip_file(self, path):
        return path not in self.files_in_version_control

    def get_files(self):
        for root, dirs, files in os.walk(self.source_root):

            def passes_all_rules(entry):
                return Ruleset.global_rules().passes(entry) and self.rules.passes(entry)

            to_keep = list(filter(passes_all_rules, dirs))
            del dirs[:]
            dirs.extend(to_keep)

            for file in files:
                file = os.path.join(root, file)
                if not passes_all_rules(file):
                    continue
                yield (file, self.get_tarball_path(file))


class Manifest(object):
    def __init__(self, manifest_filename, source_root, build_root, tarball_root='/'):
        self.current_directory = None
        self.directories = []
        self.tarball_root = tarball_root
        self.source_root = source_root
        self.build_root = build_root

        # Normalize the tarball root so that it starts and ends with a slash.
        if not self.tarball_root.endswith('/'):
            self.tarball_root = self.tarball_root + '/'
        if not self.tarball_root.startswith('/'):
            self.tarball_root = '/' + self.tarball_root

        with open(manifest_filename, 'r') as file:
            for line in file.readlines():
                self.process_line(line)

    def add_rule(self, rule):
        if self.current_directory is not None:
            self.current_directory.add_rule(rule)
        else:
            Ruleset.add_global_rule(rule)

    def add_directory(self, directory):
        self.current_directory = directory
        self.directories.append(directory)

    def get_full_source_path(self, source_path):
        if not os.path.exists(source_path):
            source_path = os.path.join(self.source_root, source_path)
        if not os.path.exists(source_path):
            raise Exception('Could not find directory %s' % source_path)
        return source_path

    def get_full_tarball_path(self, path):
        return self.tarball_root + path

    def get_source_and_tarball_paths_from_parts(self, parts):
        full_source_path = self.get_full_source_path(parts[1])
        if len(parts) > 2:
            full_tarball_path = self.get_full_tarball_path(parts[2])
        else:
            full_tarball_path = self.get_full_tarball_path(parts[1])
        return (full_source_path, full_tarball_path)

    def process_line(self, line):
        parts = line.split()
        if not parts:
            return
        if parts[0].startswith("#"):
            return

        if parts[0] == "directory" and len(parts) > 1:
            self.add_directory(Directory(*self.get_source_and_tarball_paths_from_parts(parts)))
        elif parts[0] == "file" and len(parts) > 1:
            self.add_directory(File(*self.get_source_and_tarball_paths_from_parts(parts)))
        elif parts[0] == "exclude" and len(parts) > 1:
            self.add_rule(Rule(Rule.Result.EXCLUDE, parts[1]))
        elif parts[0] == "include" and len(parts) > 1:
            self.add_rule(Rule(Rule.Result.INCLUDE, parts[1]))
        else:
            raise Exception('Line does not begin with a correct rule:\n\t' + line)

    def should_skip_file(self, directory, filename):
        # Only allow files that are not in version control when they are explicitly included in the manifest from the build dir.
        if filename.startswith(self.build_root):
            return False

        return directory.should_skip_file(filename)

    def get_files(self):
        for directory in self.directories:
            for file_tuple in directory.get_files():
                if self.should_skip_file(directory, file_tuple[0]):
                    continue
                yield file_tuple

    def create_tarfile(self, output):
        count = 0
        for file_tuple in self.get_files():
            count = count + 1

        with closing(tarfile.open(output, 'w')) as tarball:
            for i, (file_path, tarball_path) in enumerate(self.get_files(), start=1):
                print('Tarring file {0} of {1}'.format(i, count).ljust(40), end='\r')
                tarball.add(file_path, tarball_path)
        print("Wrote {0}".format(output).ljust(40))


class Distcheck(object):
    BUILD_DIRECTORY_NAME = "_build"
    INSTALL_DIRECTORY_NAME = "_install"

    def __init__(self, source_root, build_root):
        self.source_root = source_root
        self.build_root = build_root

    def extract_tarball(self, tarball_path):
        with closing(tarfile.open(tarball_path, 'r')) as tarball:
            tarball.extractall(self.build_root)

    def configure(self, dist_dir, build_dir, install_dir, port):
        def create_dir(directory, directory_type):
            try:
                os.mkdir(directory)
            except OSError as e:
                if e.errno != errno.EEXIST or not os.path.isdir(directory):
                    raise Exception("Could not create %s dir at %s: %s" % (directory_type, directory, str(e)))

        create_dir(build_dir, "build")
        create_dir(install_dir, "install")

        command = ['cmake', '-DPORT=%s' % port, '-DCMAKE_INSTALL_PREFIX=%s' % install_dir, '-DCMAKE_BUILD_TYPE=Release', '-DENABLE_GTKDOC=ON', '-DENABLE_MINIBROWSER=ON', dist_dir]
        subprocess.check_call(command, cwd=build_dir)

    def build(self, build_dir):
        command = ['make']
        make_args = os.getenv('MAKE_ARGS')
        if make_args:
            command.extend(make_args.split(' '))
        else:
            command.append('-j%d' % multiprocessing.cpu_count())
        subprocess.check_call(command, cwd=build_dir)

    def check_symbols(self, build_dir):
        check_bss = os.path.join(self.source_root, 'Tools', 'Scripts', 'check-for-global-bss-symbols-in-webkitgtk-libs')
        libjsc = os.path.join(build_dir, 'lib', 'libjavascriptcoregtk-4.1.so')
        libwk = os.path.join(build_dir, 'lib', 'libwebkit2gtk-4.1.so')
        subprocess.check_call([check_bss, libjsc, libwk])

        check_version_script = os.path.join(self.source_root, 'Tools', 'Scripts', 'check-for-invalid-symbols-in-version-script')
        version_script = os.path.join(os.path.dirname(build_dir), 'Source', 'WebKit', 'webkitglib-symbols.map')
        subprocess.check_call([check_version_script, version_script, libwk])

    def install(self, build_dir):
        subprocess.check_call(['make', 'install'], cwd=build_dir)

    def clean(self, dist_dir):
        shutil.rmtree(dist_dir)

    def check(self, tarball, port):
        tarball_name, ext = os.path.splitext(os.path.basename(tarball))
        dist_dir = os.path.join(self.build_root, tarball_name)
        build_dir = os.path.join(dist_dir, self.BUILD_DIRECTORY_NAME)
        install_dir = os.path.join(dist_dir, self.INSTALL_DIRECTORY_NAME)

        self.extract_tarball(tarball)
        self.configure(dist_dir, build_dir, install_dir, port)
        self.build(build_dir)
        if port == 'GTK':
            self.check_symbols(build_dir)
        self.install(build_dir)
        self.clean(dist_dir)

if __name__ == "__main__":
    class FilePathAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, os.path.abspath(values))

    def ensure_version_if_possible(arguments):
        if arguments.version is not None:
            return

        pkgconfig_file = os.path.join(arguments.build_dir, "Source/WebKit/webkit2gtk-4.1.pc")
        if os.path.isfile(pkgconfig_file):
            p = subprocess.Popen(['pkg-config', '--modversion', pkgconfig_file], stdout=subprocess.PIPE, text="ascii")
            version = p.communicate()[0]
            if version:
                arguments.version = version.rstrip('\n')


    def get_tarball_root_and_output_filename_from_arguments(arguments):
        tarball_root = arguments.tarball_name
        if arguments.version is not None:
            tarball_root += '-' + arguments.version

        output_filename = os.path.join(arguments.build_dir, tarball_root + ".tar")
        return tarball_root, output_filename

    parser = argparse.ArgumentParser(description='Build a distribution bundle.')
    parser.add_argument('-c', '--check', action='store_true',
                        help='Check the tarball')
    parser.add_argument('-s', '--source-dir', type=str, action=FilePathAction, default=os.getcwd(),
                        help='The top-level directory of the source distribution. ' + \
                              'Directory for relative paths. Defaults to current directory.')
    parser.add_argument('--version', type=str, default=None,
                        help='The version of the tarball to generate')
    parser.add_argument('-b', '--build-dir', type=str, action=FilePathAction, default=os.getcwd(),
                        help='The top-level path of directory of the build root. ' + \
                              'By default is the current directory.')
    parser.add_argument('-t', '--tarball-name', type=str, default='webkitgtk',
                        help='Base name of tarball. Defaults to "webkitgtk".')
    parser.add_argument('-p', '--port', type=str, default='GTK',
                        help='Port to be built in tarball check. Defaults to "GTK".')
    parser.add_argument('manifest_filename', metavar="manifest", type=str, action=FilePathAction, help='The path to the manifest file.')

    arguments = parser.parse_args()

    # Paths in the manifest are relative to the source directory, and this script assumes that
    # current working directory is the source directory, so change the current working directory
    # to be the source directory.
    os.chdir(arguments.source_dir)

    ensure_version_if_possible(arguments)
    tarball_root, output_filename = get_tarball_root_and_output_filename_from_arguments(arguments)

    manifest = Manifest(arguments.manifest_filename, arguments.source_dir, arguments.build_dir, tarball_root)
    manifest.create_tarfile(output_filename)

    if arguments.check:
        Distcheck(arguments.source_dir, arguments.build_dir).check(output_filename, arguments.port)
