from gi.repository import GObject, GLib
import threading
from ctypes import *

_backend = None
_semaphore = None

class SLU:
    #/src.new/rocio_slu -word "$prefix"_dico_word.txt -action "$prefix"_dico_action.txt -fstmodel "$prefix".fst -fstclean "$prefix"_clean_tail.fst
    def __init__(self, word_lexicon, action_lexicon, model_fst, cleaner_fst, library='slu/src.new/librocio_slu.so'):
        global _backend, _semaphore
        if _backend == None:
            _backend = cdll.LoadLibrary(library)

            # slu_t* init_slu(char* chfileword, char* chfileaction, char* chfilemodel, char* chfileclean);
            _backend.init_slu.argtypes = [c_char_p, c_char_p, c_char_p, c_char_p]
            _backend.init_slu.restype = c_void_p

            # int run_slu(slu_t* slu, char** words, int num_words, int prevn);
            _backend.run_slu.argtypes = [c_void_p, POINTER(c_char_p), c_int, c_int, c_char_p]
            _backend.run_slu.restype = c_int

            # int num_actions(slu_t* slu)
            _backend.num_actions.argtypes = [c_void_p]
            _backend.num_actions.restype = c_int
            
            # int get_action(slu_t* slu, int index)
            _backend.get_action.argtypes = [c_void_p, c_int]
            _backend.get_action.restype = c_char_p

            # void free_slu(slu_t* slu);
            _backend.free_slu.argtypes = [c_void_p]
            _backend.free_slu.restype = None

            _semaphore = threading.Semaphore()
        _semaphore.acquire()
        thread = threading.Thread(target=self._init_thread, args=[word_lexicon, action_lexicon, model_fst, cleaner_fst])
        thread.daemon = True
        thread.start()

    def _init_thread(self, word_lexicon, action_lexicon, model_fst, cleaner_fst):
        global _backend, _semaphore
        self.slu = _backend.init_slu(word_lexicon, action_lexicon, model_fst, cleaner_fst)
        _semaphore.release()

    def process(self, words, callback):
        thread = threading.Thread(target=self._process_thread, args=[words, callback])
        thread.daemon = True
        thread.start()

    def _process_thread(self, words, callback):
        global _backend, _semaphore
        c_words = (c_char_p * len(words))(*words)
        _semaphore.acquire()
        output = _backend.run_slu(self.slu, c_words, len(words), self.num_actions(), None)
        _semaphore.release()
        GLib.idle_add(callback, self, output)

    def num_actions(self):
        global _backend, _semaphore
        output = _backend.num_actions(self.slu)
        return output

    def get_action(self, index):
        global _backend, _semaphore
        output = _backend.get_action(self.slu, index)
        return output

    def shutdown(self):
        global _backend, _semaphore
        _backend.free_slu(self.slu)

if __name__ == '__main__':
    prefix = 'slu/automate/homeostasis_25nov_%s'
    slu = SLU(prefix % 'dico_word.txt', prefix % 'dico_action.txt', prefix % 'section6.fst', prefix % 'clean_tail.fst')
    #print 'before'
    slu.process(open('slu/homeostasis_25nov.asr/sect6.ref').read().strip().split(), lambda x: sys.stdout.write('%s\n' % x))
    #print 'after'
    slu.shutdown()