import numpy as np
import logging
from functools import wraps
import time


def timeit(func):
    @wraps(func)
    def timeit_wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        logging.info(f"Start Function {func.__name__}:")
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        total_time = end_time - start_time
        # first item in the args, ie `args[0]` is `self`
        logging.info(
            f'Function {func.__name__} Took {total_time:.4f} seconds')
        return result
    return timeit_wrapper


def persist_to_file(file_name):

    def decorator(original_func):
        try:
            file_nam = file_name
            if file_name[-4:] != ".npz":
                file_nam += ".npz"
            file = np.load(file_nam)
            cache = dict(zip((file.files), (file[k] for k in file.files)))
        except (IOError, ValueError):
            cache = {}

        def hash_func(*param):
            key = str(param)
            return key

        def persist_func(*param, hash=None):
            if hash is None:
                hash = hash_func(*param)
            
            print("Hash: ", hash)
            if cache == {} or ("hash" not in cache) or hash != cache["hash"]:
                print("recalc")
                data = original_func(*param)
                np.savez(file_name, hash=hash, dat=data)
                cache["hash"] = hash
                cache["dat"] = data
            print("loaded")
            return cache["dat"]

        return persist_func

    return decorator


# test = 1234
#
#
# @persist_to_file("cache.npz", test)
# def test():
#     print("calculate")
#     return np.zeros((100, 100))
#
#
# if __name__ == "__main__":
#     test()
#     test()
#     pass
