# Copyright (C) 2022 Thomas Hoppe (h0bB1T). All rights reserved.
#
# Unauthorized copying of this file via any medium is strictly prohibited.
# Proprietary and confidential.

import os

from typing import Dict, List, Tuple, Union

from ...utils.io import read_json, unified_path, write_json
from ...utils.dev import dmp
from ...constants import config_file


# The first implementation of hashing was using the first 16K data of image files (for faster hashing).
# As this may create identical hashes for similar files (e.g. brushes with large black and white starting
# areas), hash v2 was added, which uses the whole binary content of a file for hashing.
# To stay compatible with version 1.0.x, we host both hashes. On lookup for a hash, we first
# try v2 and fallback to v1 if the hash is not available. So we act transparently to the outside.
class HashRepository:
    """
    This manages binary hashes for texture entries.
    They are useful for PBR/grunge edit, to find the original image. As 
    paths categories on different machines may have different names, this is
    the only way to identify an image. Bin hashes are created from binary content of the image file.
    To not always create bin hash on startup, this data is stored in ~/.snw-hash-by-bin.cfg
    """
    def __init__(self):        
        self.modified = False # file_hashes has been modified.
        self.file_hashes = {} # type: Dict[str, str]
        self.file_hashes_v2 = {} # type: Dict[str, str]

        # Load bin hash cache.
        self.hash_file = config_file('image-hash.json')
        if os.path.exists(self.hash_file):
            self.file_hashes = read_json(self.hash_file)
        self.hash_file_v2 = config_file('image-hash-v2.json')
        if os.path.exists(self.hash_file_v2):
            self.file_hashes_v2 = read_json(self.hash_file_v2)
    

    def get_file_hash(self, image_file: str) -> Union[str, None]:
        """
        Check if bin hash for file is already in cache.
        """
        return self.file_hashes.get(unified_path(image_file), None)


    def get_file_hash_v2(self, image_file: str) -> Union[str, None]:
        """
        Check if bin hash for file is already in cache.
        """
        return self.file_hashes_v2.get(unified_path(image_file), None)        


    def add_file_hash(self, image_file: str, hash: str):
        """
        if the above is not on the cache, add it and set modification flag.
        """
        self.file_hashes[unified_path(image_file)] = hash
        self.modified = True


    def add_file_hash_v2(self, image_file: str, hash: str):
        """
        if the above is not on the cache, add it and set modification flag.
        """
        self.file_hashes_v2[unified_path(image_file)] = hash
        self.modified = True

    def save(self):
        """
        Called after every scanned folder, eventually store cache to disk.
        """
        if self.modified:
            write_json(self.hash_file, self.file_hashes)
            write_json(self.hash_file_v2, self.file_hashes_v2)
            self.modified = False 

