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

#  Copyright © 2013  B. Clausius <barcc@gmx.de>
#
#  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/>.

from __future__ import print_function, division

import sys
from multiprocessing import Pool
from multiprocessing.connection import Client

# Also defined in task.py
DBUS_PATH = '/net/launchpad/bzr_panel'
AUTHKEY = b'Wrtlprmft'


send_reply = None
send_busy_changed = None

def initializer(unique_name):
    import dbus
    global send_reply, send_busy_changed
    bus = dbus.SessionBus()
    proxy = bus.get_object(unique_name, DBUS_PATH)
    send_reply = proxy.get_dbus_method('Reply')
    send_busy_changed = proxy.get_dbus_method('BusyChanged')
    
def pool_func(sender_id, func_name, args):
    import commands
    import dbus
    import cPickle as pickle
    sender_id = dbus.UInt64(sender_id)
    func = getattr(commands, func_name)
    def reply(command, *args):
        args = dbus.ByteArray(pickle.dumps(args, protocol=2))
        send_reply(sender_id, command, args)
    try:
        send_busy_changed(True)
        func(reply, *args)
        send_busy_changed(False)
    except dbus.DBusException:
        pass
    except:
        sys.excepthook(*sys.exc_info())
    
def worker_loop(unique_name, address):
    '''This function is responsible to retrieve the tasks from the plugin,
    and dispatch them to worker threads.
    '''
    connection = Client(address, authkey=AUTHKEY)
    pool = Pool(processes=4, initializer=initializer,
                             initargs=[unique_name])
    while True:
        try:
            callback_id, func_name, args = connection.recv()
        except IOError:
            func_name = 'stop'
        if func_name == 'stop':
            break
        try:
            result = pool.apply_async(pool_func, [callback_id, func_name, args])
        except Exception as e:
            #TODO: handle error
            pass
    pool.terminate()
    pool.join()
    connection.close()
    
    
def main():
    if sys.argv[1] == 'worker_loop':
        worker_loop(*sys.argv[2:4])
        return 0
    else:
        print('unknown parameter', sys.argv[1])
    return 1
    
if __name__ == '__main__':
    sys.exit(main())

