#!/usr/bin/python3
# -*- python -*-
"""Collect helpers hook data into a single json file"""

import argparse
import json
import os
import sys
import time

import xdg.BaseDirectory

from gi.repository import GLib
from gi.repository import Gio
from gi.repository import Click

hook_ext = '.json'


def tup2variant(tup):
    builder = GLib.VariantBuilder.new(GLib.VariantType.new("(ss)"))
    builder.add_value(GLib.Variant.new_string(tup[0]))
    builder.add_value(GLib.Variant.new_string(tup[1]))
    return builder.end()


def cleanup_settings():
    settings = Gio.Settings.new('com.ubuntu.notifications.hub')
    blacklist = settings.get_value('blacklist').unpack()
    if not blacklist:
        return

    clickdb = Click.DB.new()
    clickdb.read()

    pkgnames = set()
    for package in clickdb.get_packages(False):
        pkgnames.add(package.get_property('package'))

    goodapps = GLib.VariantBuilder.new(GLib.VariantType.new("a(ss)"))

    dirty = False

    for appname in blacklist:
        if appname[0] not in pkgnames and Gio.DesktopAppInfo.new(appname[1] + ".desktop") is None:
            dirty = True
        else:
            goodapps.add_value(tup2variant(appname))

    if dirty:
        settings.set_value('blacklist', goodapps.end())


def collect_helpers(helpers_data_path, helpers_data_path_tmp, hooks_path):
    helpers_data = {}
    for hook_fname in os.listdir(hooks_path):
        if not hook_fname.endswith(hook_ext):
            continue
        try:
            with open(os.path.join(hooks_path, hook_fname), 'r') as fd:
                data = json.load(fd)
        except Exception:
            continue
        else:
            helper_id = os.path.splitext(hook_fname)[0]
            exec_path = data['exec']
            if exec_path != "":
                realpath = os.path.realpath(os.path.join(hooks_path,
                                                         hook_fname))
                exec_path = os.path.join(os.path.dirname(realpath), exec_path)
            app_id = data.get('app_id', None)
            if app_id is None:
                # no app_id, use the package name from the helper_id
                app_id = helper_id.split('_')[0]
            elif app_id.count('_') >= 3:
                # remove the version from the app_id
                app_id = app_id.rsplit('_', 1)[0]
            helpers_data[app_id] = {'exec': exec_path, 'helper_id': helper_id}

    # write the collected data to a temp file and rename the original once
    # everything is on disk
    try:
        tmp_filename = helpers_data_path_tmp % (time.time(),)
        with open(tmp_filename, 'w') as dest:
            json.dump(helpers_data, dest)
            dest.flush()
        os.rename(tmp_filename, helpers_data_path)
    except Exception:
        return True
    return False


def main(helpers_data_path=None, helpers_data_path_tmp=None, hooks_path=None):
    collect_fail = collect_helpers(helpers_data_path, helpers_data_path_tmp,
                                   hooks_path)
    clean_settings_fail = False
    try:
        cleanup_settings()
    except Exception:
        clean_settings_fail = True
    return int(collect_fail or clean_settings_fail)


if __name__ == "__main__":
    xdg_data_home = xdg.BaseDirectory.xdg_data_home
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('-d', '--data-home',
                        help='The Path to the (xdg) data home',
                        default=xdg_data_home)
    args = parser.parse_args()
    xdg_data_home = args.data_home
    helpers_data_path = os.path.join(xdg_data_home, 'ubuntu-push-client',
                                     'helpers_data.json')
    helpers_data_path_tmp = os.path.join(xdg_data_home, 'ubuntu-push-client',
                                         '.helpers_data_%s.tmp')
    hooks_path = os.path.join(xdg_data_home, 'ubuntu-push-client', 'helpers')
    sys.exit(main(helpers_data_path=helpers_data_path,
                  helpers_data_path_tmp=helpers_data_path_tmp,
                  hooks_path=hooks_path))
