#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Canonical, Ltd.
#
# Authors:
#  Ricardo Mendoza <ricardo.mendoza@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.
# 
#  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/>.
#

from gi.repository import GObject, Gio, GLib
from gi.repository import Accounts, Signon, AccountPlugin

import sys, time, dbus

permitted_accounts = {'com.google':'google', 'com.facebook.auth.login':'facebook', 'com.twitter.android.auth.login':'twitter'}

loop = GLib.MainLoop()

class Server:
    def __init__(self, proxy):
        self.accounts = []

    def get_accounts(self):
        self.accounts = []
        for acc in proxy.getAllAccounts():
            if acc[1] in permitted_accounts:
                if acc not in self.accounts:
                    self.accounts.append(acc)
        return self.accounts

class Local:
    def __init__ (self, server, indicators):
        self.local_accs = []
        self.updating = False
        self._server = server
        self._accounts_manager = Accounts.Manager() 
        services = self._accounts_manager.list_services()
        return

    def signal_handler(self, proxy, sender, signal, parameters):
        global loop
        print "SIGNAL: %s" % signal
        if signal == "AccountsUpdated":
            if not self.updating:
                loop.quit()
                self.sync_accounts(self._server)

    def get_accounts(self):
        accounts = []
        for aid in self._accounts_manager.list():
            acc = self._accounts_manager.get_account(aid)
            if acc.get_provider_name() in permitted_accounts.values():
                if acc.supports_service("documents"):
                    service = acc.get_selected_service()
                accounts.append(acc)
        return accounts

    def delete_account(self, name, provider):
        for aid in self._accounts_manager.list():
            acc = self._accounts_manager.get_account(aid)
            if (acc.get_provider_name() == provider and
                acc.get_display_name() == name):
                self._accounts_manager.delete_account(acc)
        return

    def add_account(self, name, provider):
        global loop

        self.local_accs = []

        for acc in self.get_accounts():
            self.local_accs.append((acc.get_display_name(), acc.get_provider_name()))

        if (name, provider) in self.local_accs:
            print "exists: " + name + " provider: " + provider
            return

        if permitted_accounts[provider]:
            print "creating " + name + ":" + permitted_accounts[provider]
            account = self._accounts_manager.create_account(permitted_accounts[provider])
            plugin = AccountPlugin.client_load_plugin(account)
            
            if plugin == None:
                print "Failed to load app plugin for " + account.get_display_name()
                return
            
            plugin.set_credentials(name, "")
            plugin.connect("finished", finished_cb)
    
            GLib.idle_add(plugin.act_headless)

            while (loop.is_running()):
                pass

            loop.run()       

    def sync_accounts(self, server):
        global loop
    
        self.updating = True
        
        self.local_accs = []

        for acc in self.get_accounts():
            self.local_accs.append((acc.get_display_name(), acc.get_provider_name()))

        print self.local_accs

        for account in server.get_accounts():
            name = account[0];
            provider = account[1];
    
            if permitted_accounts[provider]:
                if (name, permitted_accounts[provider]) in self.local_accs:
                    print "exists: " + name + " provider: " + provider
                    continue

                print "creating " + name + ":" + permitted_accounts[provider]
                account = self._accounts_manager.create_account(permitted_accounts[provider])
                plugin = AccountPlugin.client_load_plugin(account)
        
                if plugin == None:
                    print "Failed to load app plugin for " + account.get_display_name()
                    continue
        
                plugin.set_credentials(name, "")
                plugin.connect("finished", finished_cb)
    
                GLib.idle_add(plugin.act_headless)

                if not loop.is_running():
                    loop.run()
        
        self.updating = False

        if not loop.is_running():
            loop.run()

def finished_cb(self):
    acc = self.get_account()
    print " account created"
    services = acc.list_services()
    for service in services:
        acc.select_service(service)
        acc.set_enabled(1)
    acc.select_service(None)
    args = GLib.Variant('(ua{sv})', (acc.id, {}))
    indicators.call_sync('ReportFailure', args, 0, -1, None)
    loop.quit()
    return

if __name__ == '__main__':
    bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
    
    proxy = None

    while True:
        proxy = Gio.DBusProxy.new_sync(bus, 0, None,
                                   'com.canonical.Android',
                                   '/com/canonical/android/accounts/Accounts',
                                   'com.canonical.android.accounts.Accounts',
                                   None)
        try:
            accounts = proxy.getAllAccounts()
            break
        except GLib.GError:
            time.sleep(5)

    indicators = Gio.DBusProxy.new_sync(bus, 0, None,
                                   'com.canonical.indicators.webcredentials',
                                   '/com/canonical/indicators/webcredentials',
                                   'com.canonical.indicators.webcredentials',
                                   None)

    server = Server(proxy) 
    local = Local(server, indicators)

    proxy.connect('g-signal', local.signal_handler)

    local.sync_accounts(server)

