# Path: source/libs/search.py
# def search_abbr(keyword, data, exactmatch_priority=False): 
#     # exact match
#     if keyword in data:
#         return [keyword]
#     # no dot inside
#     if not '.' in keyword:
#         return [x for x in data if keyword in x]
#     # dot inside
#     module_names = {x : x+'.' for x in data}
#     parts = keyword.split('.')
#     for part in parts:
#         exactmatch = False
#         #print('------ PART %s -----------' % part)
#         # query has the 'misc.' form, so return everything now
#         if part == '':
#             break
#             
#         new_module_names = {}
#         for module in module_names.keys():
#             value = module_names[module]
#             # exact match?
#             if value.startswith(part+'.'):
#                 # new?
#                 if not exactmatch:
#                     #print('now running exact matches')
#                     exactmatch = True
#                     if exactmatch_priority:
#                         new_module_names = {}
#                 new_module_names[module] = value[value.index('.')+1:]
#                         
#             # not exact match
#             if not exactmatch or not exactmatch_priority:
#                 # use modules where part starts with specified part
#                 if '.' in value and value.startswith(part):
#                     #print(' match for ', module)
#                     
#                     new_module_names[module] = value[value.index('.')+1:]
#         module_names = new_module_names
#     # still too many results? if exact match desired, return only modules with lowest number of dots
#     # e.g. 'c.f' returns crypto.frequency but not crypto.frequency.etaoins
#     if exactmatch_priority:
#         minimum = min([x.count('.') for x in module_names.keys()]+[sys.maxsize])
#         for m in [x for x in module_names.keys() if x.count('.') > minimum]:
#             del module_names[m]
#     return list(module_names.keys())


import threading, time
import source.libs.define as lib
import source.libs.log as log
from source.libs.search import search_abbr
                u.stop()

        #self.lock.release()
        while len(self.jobs) > 0 and len(self.user_threads) > 0: # wait for everything to die
            time.sleep(0.5)
        self.terminate = True # sets DIE flag for itself
        self.lock.release()



    def add(self, name, start, job, timeout=None, waitfor=None):
        if self.terminate: # in terminating state, do not create anything new
            return None
        # add a new job
        self.lock.acquire()
        jobid = self.newid() # get lowest unused id
        if waitfor is None:
            self.jobs[jobid] = Job(name, start, job, timeout)
            job.start()
            log.info('Module %s will run in the background with id %d.' % (name, jobid))
        else:
            # what to wait for?
            ids_to_wait_for = []
            for x in waitfor:
                if type(x) == int:
                    ids_to_wait_for.append(x)
                elif type(x) == str:
                    if x.isdigit():
                        ids_to_wait_for.append(int(x))
                    else:

# Path: source/libs/search.py
# def search_abbr(keyword, data, exactmatch_priority=False): 
#     # exact match
#     if keyword in data:
#         return [keyword]
#     # no dot inside
#     if not '.' in keyword:
#         return [x for x in data if keyword in x]
#     # dot inside
#     module_names = {x : x+'.' for x in data}
#     parts = keyword.split('.')
#     for part in parts:
#         exactmatch = False
#         #print('------ PART %s -----------' % part)
#         # query has the 'misc.' form, so return everything now
#         if part == '':
#             break
#             
#         new_module_names = {}
#         for module in module_names.keys():
#             value = module_names[module]
#             # exact match?
#             if value.startswith(part+'.'):
#                 # new?
#                 if not exactmatch:
#                     #print('now running exact matches')
#                     exactmatch = True
#                     if exactmatch_priority:
#                         new_module_names = {}
#                 new_module_names[module] = value[value.index('.')+1:]
#                         
#             # not exact match
#             if not exactmatch or not exactmatch_priority:
#                 # use modules where part starts with specified part
#                 if '.' in value and value.startswith(part):
#                     #print(' match for ', module)
#                     
#                     new_module_names[module] = value[value.index('.')+1:]
#         module_names = new_module_names
#     # still too many results? if exact match desired, return only modules with lowest number of dots
#     # e.g. 'c.f' returns crypto.frequency but not crypto.frequency.etaoins
#     if exactmatch_priority:
#         minimum = min([x.count('.') for x in module_names.keys()]+[sys.maxsize])
#         for m in [x for x in module_names.keys() if x.count('.') > minimum]:
#             del module_names[m]
#     return list(module_names.keys())


# Path: source/libs/scheduler.py
import threading, time
import source.libs.define as lib
import source.libs.log as log
from source.libs.search import search_abbr

                u.stop()

        #self.lock.release()
        while len(self.jobs) > 0 and len(self.user_threads) > 0: # wait for everything to die
            time.sleep(0.5)
        self.terminate = True # sets DIE flag for itself
        self.lock.release()



    def add(self, name, start, job, timeout=None, waitfor=None):
        if self.terminate: # in terminating state, do not create anything new
            return None
        # add a new job
        self.lock.acquire()
        jobid = self.newid() # get lowest unused id
        if waitfor is None:
            self.jobs[jobid] = Job(name, start, job, timeout)
            job.start()
            log.info('Module %s will run in the background with id %d.' % (name, jobid))
        else:
            # what to wait for?
            ids_to_wait_for = []
            for x in waitfor:
                if type(x) == int:
                    ids_to_wait_for.append(x)
                elif type(x) == str:
                    if x.isdigit():
                        ids_to_wait_for.append(int(x))
                    else:

                        matches = search_abbr(x, lib.modules.keys())