# Copyright (c) 2017-2018 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
# 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, either version 3 of the License, or
# (at your option) any later version.
# 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 gi
gi.require_version('Secret', '1')
from gi.repository import Secret, GLib

from passbook.define import App
from passbook.logger import Logger


class SecretsHelper:
    """
        Simpler helper for Secret
    """
    def load_collections(callback):
        def on_load_collections(source, result, callback):
            try:
                source.load_collections_finish(result)
            except Exception as e:
                Logger.error("SecretsHelper::on_load_collections(): %s" % e)
            callback(source)

        def on_get_service(source, result, callback):
            try:
                service = Secret.Service.get_finish(result)
                service.load_collections(None, on_load_collections, callback)
            except Exception as e:
                Logger.error("SecretsHelper::on_get_service(): %s" % e)
        Secret.Service.get(Secret.ServiceFlags.OPEN_SESSION, None,
                           on_get_service, callback)

    def __init__(self):
        """
            Init helper
        """
        pass

    def add_collection(self, name, callback, *args):
        """
            Add a new collection
            @param name a str
            @param callback as function
        """
        try:
            def on_create(secret, result, callback, *args):
                try:
                    collection = Secret.Collection.create_finish(result)
                    callback(collection, *args)
                except Exception as e:
                    Logger.error("SecretsHelper::on_create(): %s", e)
            Secret.Collection.create(
                         None, name, None,
                         Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE,
                         None, on_create, callback, *args)
        except Exception as e:
            Logger.error("SecretsHelper::add_collection(): %s", e)

    def remove_collection(self, collection, callback, *args):
        """
            Remove collection
            @param collection as Secret.Collection
            @param callback as function
        """
        try:
            def on_delete(collection, result, callback, *args):
                try:
                    collection.delete_finish(result)
                    callback(*args)
                except Exception as e:
                    Logger.error("SecretsHelper::on_delete(): %s", e)
            collection.delete(None, on_delete, callback, *args)
        except Exception as e:
            Logger.error("SecretsHelper::remove_collection(): %s", e)

    def add_password(self, collection, desc, login, password, callback, *args):
        """
            Add a new password
            @param collection as Secret.Collection
            @param desc as str
            @param login a str
            @param password as str
            @param callback as function
        """
        try:
            def on_create(secret, result, callback, *args):
                try:
                    item = Secret.Item.create_finish(result)
                    callback(collection, item, *args)
                except Exception as e:
                    Logger.error("SecretsHelper::on_create(): %s", e)
            attributes_types = {
                "login": Secret.SchemaAttributeType.STRING
            }
            attributes_name = {
                "login": login
            }
            value = Secret.Value(password, len(password), "text/plain")
            schema = Secret.Schema.new("org.freedesktop.Secret.Generic",
                                       Secret.SchemaFlags.NONE,
                                       attributes_types)
            Secret.Item.create(
                         collection, schema,
                         attributes_name, desc, value,
                         Secret.ItemCreateFlags.NONE,
                         None, on_create, callback, *args)
        except Exception as e:
            Logger.error("SecretsHelper::add_password(): %s", e)

    def get_collections(self, callback, *args):
        """
            Get all collections
            @param callback as function
        """
        if App().secret_service is None:
            Logger.debug("SecretsHelper::get_collections(): waiting")
            GLib.timeout_add(250, self.get_collections, callback, *args)
            return
        try:
            collections = App().secret_service.get_collections()
            callback(collections, *args)
        except Exception as e:
            Logger.error("SecretsHelper::get_collections(): %s", e)

    def get_collection(self, alias, callback, *args):
        """
            Get login collection
            @param alias as str
            @param callback as function
        """
        if App().secret_service is None:
            Logger.debug("SecretsHelper::get_default_collection(): waiting")
            GLib.timeout_add(250, self.get_collection, alias, callback, *args)
            return

        def on_alias(source, result, callback, *args):
            try:
                collection = Secret.Collection.for_alias_finish(result)
                callback(collection, *args)
            except Exception as e:
                Logger.error("SecretsHelper::on_alias(): %s", e)
        try:
            Secret.Collection.for_alias(None,
                                        Secret.COLLECTION_DEFAULT,
                                        Secret.CollectionFlags.NONE,
                                        None,
                                        on_alias,
                                        callback,
                                        *args)
        except Exception as e:
            Logger.error("SecretsHelper::get_login_collection(): %s", e)

    def unlock(self, collection, callback, *args):
        """
            Unlock secrets
            @param collection as Gio.DBusProxy
            @param callback as function
        """
        def on_unlock(secret, result, callback, *args):
            try:
                (count, collections) = secret.unlock_finish(result)
                callback(collections[0], *args)
            except Exception as e:
                Logger.error("SecretsHelper::on_unlock(): %s", e)
        try:
            collection.get_service().unlock([collection], None,
                                            on_unlock, callback, *args)
        except Exception as e:
            Logger.error("SecretsHelper::unlock(): %s", e)

#######################
# PRIVATE             #
#######################
