import ezrun
import hashlib
import os
import dill
import inspect
import time

# should make a record of who you're waiting for
# when waiting should wait on those jobs only
# should also wait until results files are available
# should get preferences at initialization

def just_hash_it(*stuff):
    return hashlib.md5((str(*stuff)).encode('UTF8')).hexdigest()

class ezcache:
    def __init__(self,fun,directory='/home/domke/work1/divide_and_couple',name=None,resid=None,ncores=1,mem=100,submit=None,hours=12,minutes=0):
        self.fun = fun
        self.fun_name  = self.fun.__name__
        self.fun_hash   = just_hash_it(inspect.getsource(self.fun))
        self.directory = directory
        print('fun name',self.fun_name)
        print('fun hash',self.fun_hash)
        self.prefs = {'name':name,'resid':resid,'ncores':ncores,'mem':mem,'submit':submit,'hours':hours,'minutes':minutes}
        self.fnames_waiting_on = []

    def get_fname(self,*args):
        # do we want to use the name? I guess it's OK...
        return self.fun_name+'_'+self.fun_hash+'_'+just_hash_it(*args)

    def run(self,*args):
        fname = self.get_fname(*args)
        if os.path.isfile(fname):
            print('results already exist - returning')
            return
        print('will save to',fname)
        def myfun(*args):
            import dill
            rez = self.fun(*args)
            print('rez (insidem myfun)',rez)
            with open(fname,'wb') as f:
                dill.dump(rez,f)

        self.fnames_waiting_on.append(fname)
        ezrun.run(myfun,*args,**self.prefs)

    def get(self,*args):
        fname = self.get_fname(*args)
        if os.path.isfile(fname):
            with open(fname, 'rb') as f:
                return dill.load(f)
        else:
            error_msg = 'results do not exist for: ' + fname
            print('fname:',fname)
            raise Exception(error_msg)

    def wait_for_complete(self):
        while True:
            # for fname in self.fnames_waiting_on:
            #     print('looking for ',fname,end='')
            #     if not os.path.isfile(fname):
            #         print('-- not found')
            #         all_found = False
            #         time.sleep(.1)
            #         break
            found = [os.path.isfile(fname) for fname in self.fnames_waiting_on]
            print('# found',sum(found), 'total', len(self.fnames_waiting_on))
            if all(found):
                print('all found!')
                break
            time.sleep(1)
        # secondary loop to make sure files are done being modified
        while True:
            print('fnames',self.fnames_waiting_on)
            age = [time.time()-os.path.getmtime(fname) for fname in self.fnames_waiting_on]
            print('age',age)
            if min(age) >  5.0:
                break

        #ezrun.wait_for_complete()