#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Copyright (C) 2016 Canonical Ltd.
# Author: Christopher Townsend <christopher.townsend@canonical.com>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import json
import libertine.utils
import os
import shlex
import shutil
import subprocess

from gi.repository import GLib, Gio

puritine_hook_dir = os.path.join(os.environ['HOME'], '.cache', 'libertine', 'puritine')
puritine_symlink_farm_file = os.path.join(puritine_hook_dir, 'PuritineSymlinkFarm.json')
puritine_click_config_file = os.path.join('libertine-config', 'libertine', 'ContainersConfig.json')


def symlink_farm_entries_count():
    if (puritine_symlink_farm_list and
        puritine_symlink_farm_list['customContainers']):
        return len(puritine_symlink_farm_list['customContainers'])

    return 0


def puritine_symlink_exists(symlink):
    for file in os.listdir(puritine_hook_dir):
        if file == symlink:
            return True

    return False


def get_symlink_name(puritine_symlink_farm_list, container_id):
    if puritine_symlink_farm_list:
        for container in puritine_symlink_farm_list['customContainers']:
            if container['id'] == container_id:
                return (puritine_symlink_farm_list['customContainers'].index(container), container['symlinkName'])

    return (0, None)


def find_removed_puritine_symlinks(puritine_symlink_farm_list):
    for container in puritine_symlink_farm_list['customContainers']:
        if puritine_symlink_exists(container['symlinkName']):
            continue
        else:
            manager_cmd = "libertine-container-manager destroy -i " + container['id']
            cmd = shlex.split(manager_cmd)
            subprocess.Popen(cmd).wait()
            puritine_symlink_farm_list['customContainers'].remove(container)

    return puritine_symlink_farm_list


def find_new_or_updated_puritine_symlinks(puritine_symlink_farm_list):
    symlinks = os.listdir(puritine_hook_dir)

    for symlink in symlinks:
        puritine_click_path = os.path.join(puritine_hook_dir, symlink)
        if not os.path.islink(puritine_click_path):
            continue

        config_file_path = os.path.join(puritine_click_path, puritine_click_config_file)

        with open(config_file_path, 'r') as fd:
            container_list = json.load(fd)

        container_id = container_list['containerList'][0]['id']

        (index, symlink_name) = get_symlink_name(puritine_symlink_farm_list, container_id)

        if symlink_name:
            # Package exists and symlink name is the same- no update
            if symlink_name == symlink:
                continue
            else:
                puritine_symlink_farm_list['customContainers'][index]['symlinkName'] = symlink
        else:
            symlink_obj = {'symlinkName': symlink, 'id': container_id}
            if 'customContainers' not in puritine_symlink_farm_list:
                puritine_symlink_farm_list['customContainers'] = [symlink_obj]
            else:
                puritine_symlink_farm_list['customContainers'].append(symlink_obj)

        puritine_click_rootfs_path = os.path.join(puritine_click_path, 'libertine-data', 'libertine-container',
                                                  container_id, 'rootfs')

        libertine_containers_path = libertine.utils.get_libertine_containers_dir_path()
        puritine_container_path = os.path.join(libertine_containers_path, container_id)
        puritine_container_rootfs_path = os.path.join(puritine_container_path, 'rootfs')

        if not os.path.exists(puritine_container_path):
            os.makedirs(puritine_container_path)
        else:
            os.remove(puritine_container_rootfs_path)

        # Link to the click packages container
        os.symlink(puritine_click_rootfs_path, puritine_container_rootfs_path)

        # Copy any user data that does not exist
        libertine_user_data_path = libertine.utils.get_libertine_container_userdata_dir_path(container_id)
        if not os.path.exists(libertine_user_data_path):
            puritine_click_user_data_path = os.path.join(puritine_click_path, 'libertine-config', 'libertine-container',
                                                         'user-data', container_id)
            shutil.copytree(puritine_click_user_data_path, libertine_user_data_path)

        # Update the main ContainerConfig.json
        manager_cmd = "libertine-container-manager merge-configs -f " +  config_file_path
        cmd = shlex.split(manager_cmd)
        subprocess.Popen(cmd).wait()

    return puritine_symlink_farm_list


def favorite_libertine_scope():
    libertine_scope_value = 'scope://libertine-scope.ubuntu_libertine-scope'
    click_scope_value = 'scope://clickscope'
    schema = 'com.canonical.Unity.Dash'
    schema_key = 'favorite-scopes'

    settings = Gio.Settings.new(schema)

    favorites = settings.get_value(schema_key)

    array = favorites.dup_strv()

    if not libertine_scope_value in array:
        array.insert(array.index(click_scope_value) + 1, libertine_scope_value)
        new_favorites = GLib.Variant.new_strv(array)
        settings.set_value(schema_key, new_favorites)
        del new_favorites

    del array
    del favorites
    del settings


if __name__ == '__main__':
    puritine_symlink_farm_list = {}
    update_libertine_scope = libertine.utils.set_session_dbus_env_var()

    if not os.path.exists(puritine_hook_dir):
        os.makedirs(puritine_hook_dir)

    if (os.path.exists(puritine_symlink_farm_file) and
        os.path.getsize(puritine_symlink_farm_file) != 0):
        with open(puritine_symlink_farm_file, 'r') as fd:
            puritine_symlink_farm_list = json.load(fd)

    count_at_start = symlink_farm_entries_count()

    puritine_symlink_farm_list = find_new_or_updated_puritine_symlinks(puritine_symlink_farm_list)

    if puritine_symlink_farm_list:
        puritine_symlink_farm_list = find_removed_puritine_symlinks(puritine_symlink_farm_list)

    count_at_finish = symlink_farm_entries_count()

    with open(puritine_symlink_farm_file, 'w') as fd:
        json.dump(puritine_symlink_farm_list, fd, sort_keys=True, indent=4)
        fd.write('\n')

    if count_at_start == 0 and count_at_finish > 0 and update_libertine_scope:
        favorite_libertine_scope()

    if update_libertine_scope:
        libertine.utils.refresh_libertine_scope()
