#
#  Copyright (C) 2017 Codethink Limited
#
#  This program 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, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Jürg Billeter <juerg.billeter@codethink.co.uk>
#        Andrew Leeming <andrew.leeming@codethink.co.uk>
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
#
# Code based on Jürg's artifact cache and Andrew's ostree plugin
#

# Disable pylint warnings that are not appicable to this module
# pylint: disable=bad-exception-context,catching-non-exception

import os
from collections import namedtuple

import gi
from gi.repository.GLib import Variant, VariantDict

from ._exceptions import BstError, ErrorDomain

# pylint: disable=wrong-import-position,wrong-import-order
gi.require_version('OSTree', '1.0')
from gi.repository import GLib, Gio, OSTree  # nopep8


# For users of this file, they must expect (except) it.
class OSTreeError(BstError):
    def __init__(self, message, reason=None):
        super().__init__(message, domain=ErrorDomain.UTIL, reason=reason)


# ensure()
#
# Args:
#    path (str): The file path to where the desired repo should be
#    compress (bool): use compression or not when creating
#
# Returns: an OSTree.Repo
def ensure(path, compress):

    # create also succeeds on existing repository
    repo = OSTree.Repo.new(Gio.File.new_for_path(path))
    mode = OSTree.RepoMode.ARCHIVE_Z2 if compress \
        else OSTree.RepoMode.BARE_USER

    repo.create(mode)

    # Disble OSTree's built in minimum-disk-space check.
    config = repo.copy_config()
    config.set_string('core', 'min-free-space-percent', '0')
    repo.write_config(config)
    repo.reload_config()

    return repo


# checkout()
#
# Checkout the content at 'commit' from 'repo' in
# the specified 'path'
#
# Args:
#    repo (OSTree.Repo): The repo
#    path (str): The checkout path
#    commit_ (str): The commit checksum to checkout
#    user (boot): Whether to checkout in user mode
#
def checkout(repo, path, commit_, user=False):

    # Check out a full copy of an OSTree at a given ref to some directory.
    #
    # Note: OSTree does not like updating directories inline/sync, therefore
    # make sure you checkout to a clean directory or add additional code to support
    # union mode or (if it exists) file replacement/update.
    #
    # Returns True on success
    #
    # cli exmaple:
    #   ostree --repo=repo checkout --user-mode runtime/org.freedesktop.Sdk/x86_64/1.4 foo
    os.makedirs(os.path.dirname(path), exist_ok=True)

    options = OSTree.RepoCheckoutAtOptions()

    # For repos which contain root owned files, we need
    # to checkout with OSTree.RepoCheckoutMode.USER
    #
    # This will reassign uid/gid and also munge the
    # permission bits a bit.
    if user:
        options.mode = OSTree.RepoCheckoutMode.USER

    # Using AT_FDCWD value from fcntl.h
    #
    # This will be ignored if the passed path is an absolute path,
    # if path is a relative path then it will be appended to the
    # current working directory.
    AT_FDCWD = -100
    try:
        repo.checkout_at(options, AT_FDCWD, path, commit_)
    except GLib.GError as e:
        raise OSTreeError("Failed to checkout commit '{}': {}".format(commit_, e.message)) from e


# commit():
#
# Commit built artifact to cache.
#
# Files are all recorded with uid/gid 0
#
# Args:
#    repo (OSTree.Repo): The repo
#    dir_ (str): The source directory to commit to the repo
#    refs (list): A list of symbolic references (tag) for the commit
#
def commit(repo, dir_, refs):

    def commit_filter(repo, path, file_info):

        # For now, just set everything in the repo as uid/gid 0
        #
        # In the future we'll want to extract virtualized file
        # attributes from a fuse layer and use that.
        #
        file_info.set_attribute_uint32('unix::uid', 0)
        file_info.set_attribute_uint32('unix::gid', 0)

        return OSTree.RepoCommitFilterResult.ALLOW

    commit_modifier = OSTree.RepoCommitModifier.new(
        OSTree.RepoCommitModifierFlags.NONE, commit_filter)

    repo.prepare_transaction()
    try:
        # add tree to repository
        mtree = OSTree.MutableTree.new()
        repo.write_directory_to_mtree(Gio.File.new_for_path(dir_),
                                      mtree, commit_modifier)
        _, root = repo.write_mtree(mtree)

        # create root commit object, no parent, no branch
        _, rev = repo.write_commit(None, None, None, None, root)

        # create refs
        for ref in refs:
            repo.transaction_set_ref(None, ref, rev)

        # complete repo transaction
        repo.commit_transaction(None)
    except GLib.GError as e:

        # Reraise any error as a buildstream error
        repo.abort_transaction()
        raise OSTreeError(e.message) from e


# set_ref():
#
# Set symbolic reference to specified revision.
#
# Args:
#    repo (OSTree.Repo): The repo
#    ref (str): A symbolic reference (tag) for the commit
#    rev (str): Commit checksum
#
def set_ref(repo, ref, rev):

    repo.prepare_transaction()
    try:
        repo.transaction_set_ref(None, ref, rev)

        # complete repo transaction
        repo.commit_transaction(None)
    except:
        repo.abort_transaction()
        raise


# exists():
#
# Checks wether a given commit or symbolic ref exists and
# is locally cached in the specified repo.
#
# Args:
#    repo (OSTree.Repo): The repo
#    ref (str): A commit checksum or symbolic ref
#
# Returns:
#    (bool): Whether 'ref' is valid in 'repo'
#
def exists(repo, ref):

    # Get the commit checksum, this will:
    #
    #  o Return a commit checksum if ref is a symbolic branch
    #  o Return the same commit checksum if ref is a valid commit checksum
    #  o Return None if the ostree repo doesnt know this ref.
    #
    ref = checksum(repo, ref)
    if ref is None:
        return False

    # If we do have a ref which the ostree knows about, this does
    # not mean we necessarily have the object locally (we may just
    # have some metadata about it, this can happen).
    #
    # Use has_object() only with a resolved valid commit checksum
    # to check if we actually have the object locally.
    _, has_object = repo.has_object(OSTree.ObjectType.COMMIT, ref, None)
    return has_object


# remove():
#
# Removes the given commit or symbolic ref from the repo.
#
# Args:
#    repo (OSTree.Repo): The repo
#    ref (str): A commit checksum or symbolic ref
#    defer_prune (bool): Whether to defer pruning to the caller. NOTE:
#                        The space won't be freed until you manually
#                        call repo.prune.
#
# Returns:
#    (int|None) The amount of space pruned from the repository in
#               Bytes, or None if defer_prune is True
#
def remove(repo, ref, *, defer_prune=False):

    # Get the commit checksum, this will:
    #
    #  o Return a commit checksum if ref is a symbolic branch
    #  o Return the same commit checksum if ref is a valid commit checksum
    #  o Return None if the ostree repo doesnt know this ref.
    #
    check = checksum(repo, ref)
    if check is None:
        raise OSTreeError("Could not find artifact for ref '{}'".format(ref))

    repo.set_ref_immediate(None, ref, None)

    if not defer_prune:
        _, _, _, pruned = repo.prune(OSTree.RepoPruneFlags.REFS_ONLY, -1)
        return pruned

    return None


# checksum():
#
# Returns the commit checksum for a given symbolic ref,
# which might be a branch or tag. If it is a branch,
# the latest commit checksum for the given branch is returned.
#
# Args:
#    repo (OSTree.Repo): The repo
#    ref (str): The symbolic ref
#
# Returns:
#    (str): The commit checksum, or None if ref does not exist.
#
def checksum(repo, ref):

    _, checksum_ = repo.resolve_rev(ref, True)
    return checksum_


OSTREE_GIO_FAST_QUERYINFO = ("standard::name,standard::type,standard::size,"
                             "standard::is-symlink,standard::symlink-target,"
                             "unix::device,unix::inode,unix::mode,unix::uid,"
                             "unix::gid,unix::rdev")


DiffItem = namedtuple('DiffItem', ['src', 'src_info',
                                   'target', 'target_info',
                                   'src_checksum', 'target_checksum'])


# diff_dirs():
#
# Compute the difference between directory a and b as 3 separate sets
# of OSTree.DiffItem.
#
# This is more-or-less a direct port of OSTree.diff_dirs (which cannot
# be used via PyGobject), but does not support options.
#
# Args:
#    a (Gio.File): The first directory for the comparison.
#    b (Gio.File): The second directory for the comparison.
#
# Returns:
#    (modified, removed, added)
#
def diff_dirs(a, b):
    # get_file_checksum():
    #
    # Helper to compute the checksum of an arbitrary file (different
    # objects have different methods to compute these).
    #
    def get_file_checksum(f, f_info):
        if isinstance(f, OSTree.RepoFile):
            return f.get_checksum()
        else:
            contents = None
            if f_info.get_file_type() == Gio.FileType.REGULAR:
                contents = f.read()

            csum = OSTree.checksum_file_from_input(f_info, None, contents,
                                                   OSTree.ObjectType.FILE)
            return OSTree.checksum_from_bytes(csum)

    # diff_files():
    #
    # Helper to compute a diff between two files.
    #
    def diff_files(a, a_info, b, b_info):
        checksum_a = get_file_checksum(a, a_info)
        checksum_b = get_file_checksum(b, b_info)

        if checksum_a != checksum_b:
            return DiffItem(a, a_info, b, b_info, checksum_a, checksum_b)

        return None

    # diff_add_dir_recurse():
    #
    # Helper to collect all files in a directory recursively.
    #
    def diff_add_dir_recurse(d):
        added = []

        dir_enum = d.enumerate_children(OSTREE_GIO_FAST_QUERYINFO,
                                        Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)

        for child_info in dir_enum:
            name = child_info.get_name()
            child = d.get_child(name)
            added.append(child)

            if child_info.get_file_type() == Gio.FileType.DIRECTORY:
                added.extend(diff_add_dir_recurse(child))

        return added

    modified = []
    removed = []
    added = []

    child_a_info = a.query_info(OSTREE_GIO_FAST_QUERYINFO,
                                Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
    child_b_info = b.query_info(OSTREE_GIO_FAST_QUERYINFO,
                                Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)

    # If both are directories and have the same checksum, we know that
    # none of the underlying files changed, so we can save time.
    if (child_a_info.get_file_type() == Gio.FileType.DIRECTORY and
            child_b_info.get_file_type() == Gio.FileType.DIRECTORY and
            isinstance(a, OSTree.RepoFileClass) and
            isinstance(b, OSTree.RepoFileClass)):
        if a.tree_get_contents_checksum() == b.tree_get_contents_checksum():
            return modified, removed, added

    # We walk through 'a' first
    dir_enum = a.enumerate_children(OSTREE_GIO_FAST_QUERYINFO,
                                    Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
    for child_a_info in dir_enum:
        name = child_a_info.get_name()

        child_a = a.get_child(name)
        child_a_type = child_a_info.get_file_type()

        try:
            child_b = b.get_child(name)
            child_b_info = child_b.query_info(OSTREE_GIO_FAST_QUERYINFO,
                                              Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
        except GLib.Error as e:
            # If the file does not exist in b, it has been removed
            if e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND):
                removed.append(child_a)
                continue
            else:
                raise

        # If the files differ but are of different types, we report a
        # modification, saving a bit of time because we won't need a
        # checksum
        child_b_type = child_b_info.get_file_type()
        if child_a_type != child_b_type:
            diff_item = DiffItem(child_a, child_a_info,
                                 child_b, child_b_info,
                                 None, None)
            modified.append(diff_item)
        # Finally, we compute checksums and compare the file contents directly
        else:
            diff_item = diff_files(child_a, child_a_info, child_b, child_b_info)

            if diff_item:
                modified.append(diff_item)

            # If the files are both directories, we recursively use
            # this function to find differences - saving time if they
            # are equal.
            if child_a_type == Gio.FileType.DIRECTORY:
                subdir = diff_dirs(child_a, child_b)
                modified.extend(subdir[0])
                removed.extend(subdir[1])
                added.extend(subdir[2])

    # Now we walk through 'b' to find any files that were added
    dir_enum = b.enumerate_children(OSTREE_GIO_FAST_QUERYINFO,
                                    Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
    for child_b_info in dir_enum:
        name = child_b_info.get_name()

        child_b = b.get_child(name)

        try:
            child_a = a.get_child(name)
            child_a_info = child_a.query_info(OSTREE_GIO_FAST_QUERYINFO,
                                              Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS)
        except GLib.Error as e:
            # If the file does not exist in 'a', it was added.
            if e.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND):
                added.append(child_b)
                if child_b_info.get_file_type() == Gio.FileType.DIRECTORY:
                    added.extend(diff_add_dir_recurse(child_b))
                continue
            else:
                raise

    return modified, removed, added


# fetch()
#
# Fetch new objects from a remote, if configured
#
# Args:
#    repo (OSTree.Repo): The repo
#    remote (str): An optional remote name, defaults to 'origin'
#    ref (str): An optional ref to fetch, will reduce the amount of objects fetched
#    progress (callable): An optional progress callback
#
# Note that a commit checksum or a branch reference are both
# valid options for the 'ref' parameter. Using the ref parameter
# can save a lot of bandwidth but mirroring the full repo is
# still possible.
#
def fetch(repo, remote="origin", ref=None, progress=None):
    # Fetch metadata of the repo from a remote
    #
    # cli example:
    #  ostree --repo=repo pull --mirror freedesktop:runtime/org.freedesktop.Sdk/x86_64/1.4
    def progress_callback(info):
        status = async_progress.get_status()
        outstanding_fetches = async_progress.get_uint('outstanding-fetches')
        bytes_transferred = async_progress.get_uint64('bytes-transferred')
        fetched = async_progress.get_uint('fetched')
        requested = async_progress.get_uint('requested')

        if status:
            progress(0.0, status)
        elif outstanding_fetches > 0:
            formatted_bytes = GLib.format_size_full(bytes_transferred, 0)
            if requested == 0:
                percent = 0.0
            else:
                percent = (fetched * 1.0 / requested) * 100

            progress(percent,
                     "Receiving objects: {:d}% ({:d}/{:d}) {}".format(int(percent), fetched,
                                                                      requested, formatted_bytes))
        else:
            progress(100.0, "Writing Objects")

    async_progress = None
    if progress is not None:
        async_progress = OSTree.AsyncProgress.new()
        async_progress.connect('changed', progress_callback)

    # FIXME: This hangs the process and ignores keyboard interrupt,
    #        fix this using the Gio.Cancellable
    refs = None
    if ref is not None:
        refs = [ref]

    try:
        repo.pull(remote,
                  refs,
                  OSTree.RepoPullFlags.MIRROR,
                  async_progress,
                  None)  # Gio.Cancellable
    except GLib.GError as e:
        if ref is not None:
            raise OSTreeError("Failed to fetch ref '{}' from '{}': {}".format(ref, remote, e.message)) from e
        else:
            raise OSTreeError("Failed to fetch from '{}': {}".format(remote, e.message)) from e


# configure_remote():
#
# Ensures a remote is setup to a given url.
#
# Args:
#    repo (OSTree.Repo): The repo
#    remote (str): The name of the remote
#    url (str): The url of the remote ostree repo
#    key_url (str): The optional url of a GPG key (should be a local file)
#
def configure_remote(repo, remote, url, key_url=None):
    # Add a remote OSTree repo. If no key is given, we disable gpg checking.
    #
    # cli exmaple:
    #   wget https://sdk.gnome.org/keys/gnome-sdk.gpg
    #   ostree --repo=repo --gpg-import=gnome-sdk.gpg remote add freedesktop https://sdk.gnome.org/repo
    options = None  # or GLib.Variant of type a{sv}
    if key_url is None:
        vd = VariantDict.new()
        vd.insert_value('gpg-verify', Variant.new_boolean(False))
        options = vd.end()

    try:
        repo.remote_change(None,      # Optional OSTree.Sysroot
                           OSTree.RepoRemoteChange.ADD_IF_NOT_EXISTS,
                           remote,    # Remote name
                           url,       # Remote url
                           options,   # Remote options
                           None)      # Optional Gio.Cancellable
    except GLib.GError as e:
        raise OSTreeError("Failed to configure remote '{}': {}".format(remote, e.message)) from e

    # Remote needs to exist before adding key
    if key_url is not None:
        try:
            gfile = Gio.File.new_for_uri(key_url)
            stream = gfile.read()
            repo.remote_gpg_import(remote, stream, None, 0, None)
        except GLib.GError as e:
            raise OSTreeError("Failed to add gpg key from url '{}': {}".format(key_url, e.message)) from e


# list_artifacts():
#
# List cached artifacts in Least Recently Modified (LRM) order.
#
# Returns:
#     (list) - A list of refs in LRM order
#
def list_artifacts(repo):
    # string of: /path/to/repo/refs/heads
    ref_heads = os.path.join(repo.get_path().get_path(), 'refs', 'heads')

    # obtain list of <project>/<element>/<key>
    refs = _list_all_refs(repo).keys()

    mtimes = []
    for ref in refs:
        ref_path = os.path.join(ref_heads, ref)
        if os.path.exists(ref_path):
            # Obtain the mtime (the time a file was last modified)
            mtimes.append(os.path.getmtime(ref_path))

    # NOTE: Sorted will sort from earliest to latest, thus the
    # first element of this list will be the file modified earliest.
    return [ref for _, ref in sorted(zip(mtimes, refs))]


# _list_all_refs():
#
# Create a list of all refs.
#
# Args:
#    repo (OSTree.Repo): The repo
#
# Returns:
#    (dict): A dict of refs to checksums.
#
def _list_all_refs(repo):
    try:
        _, refs = repo.list_refs(None)
        return refs
    except GLib.GError as e:
        raise OSTreeError(message=e.message) from e
