import json
import fcntl
from pathlib import Path

class Cache:
    def __init__(self, cache_dir, num_env):
        self.cache_path = Path(cache_dir)
        self.cache = self.load_cache()
        self.update_threshold = 1
        self.update_count = 0

    def load_cache(self):
        if self.cache_path.exists():
            try:
                cache = {}
                with open(self.cache_path, 'r') as f:
                    fcntl.flock(f, fcntl.LOCK_EX)
                    for line in f:
                        data = json.loads(line)
                        cache.update(data)
                    fcntl.flock(f, fcntl.LOCK_UN)
                print("Cache loaded successfully.")
                return cache
            except Exception as e:
                print(f'Error loading cache: {e}')
                return {}
        else:
            return {}

    def save_cache(self):
        try:
            with open(self.cache_path, 'w') as f:
                fcntl.flock(f, fcntl.LOCK_EX)
                for key, value in self.cache.items():
                    json.dump({key: value}, f)
                    f.write('\n')
                fcntl.flock(f, fcntl.LOCK_UN)
            print("Cache saved successfully.")
        except Exception as e:
            print(f'Error saving cache: {e}')

    def load_and_save_cache(self):
        new_cache = self.load_cache()
        # Combine existing and new cache, giving priority to new_cache
        combined_cache = {**new_cache, **self.cache}
        self.cache = combined_cache
        self.save_cache()

    def store_in_cache(self, key, value):
        self.cache[key] = value
        self.update_count += 1
        if self.update_count >= self.update_threshold:
            self.load_and_save_cache()
            self.update_count = 0

    def check_in_cache(self, inputs):
        return inputs in self.cache

    def retrieve_from_cache(self, inputs):
        return self.cache.get(inputs, None)