"""
FOR PROPER DOCUMENTATION INFORMATION SEE DOCS.MD
MAP Databasing System © 2025 by Pixelated Dream is licensed under Creative Commons Attribution-NoDerivatives 4.0 International
WE ARE NOT RESPONSIBLE FOR LOSS OF DATA WHEN USING THIS SOFTWARE
This library has very minimal and non-involved error handling so please always double-check documentation and information-
to prevent data loss or other issues.

Metadata / Build Info
? Version: b0.1.1
? File: mapdbsys.py
? ID: MAPDBSystem
? Name: MAP Databasing System
? GeneralAuthor: Pixelated Dream
? Developers:
? | Harvey Jass
? Date: 5/31/2025
? URLs: # Currently inaccurate
? | https://pixelateddream.net/software/map-db-system?v="b0.1.0"
"""

# ===========================================================================
#   LIBRARY FUNCTIONS
# ===========================================================================

def map_to_dict(mapfile): # Expects the full mapfile as a byte string
    entries = [e for e in mapfile.split(b'\xa0') if e] # Splits entire file into individual entries AND ensures no trailing entry with no content
    result = {} # Predefining result dictionary
    for entry in entries: # Iterates through all entries
        parts = entry.split(b'\x00') # Splits entry into a key and its values
        if parts: # Safety check
            key = parts[0].decode() # Decodes the key from a byte string into a regular string for convenience. YOUR WELCOME!!
            values = [p.decode() for p in parts[1:]] # Selects all elements but the key, decodes them into regular strings for convenience (again, YOU ARE VERY FRACKING WELCOME!!!!!), and compiles them into a list
            result[key] = values # Pairs the key to its values in the result dictionary
    return result # Returns the resulting dictionary

def dict_to_map(dictionary): # Expects a dictionary with a key and a list of values in string format
    entries = [] # Predefining temporary entry list
    for key, values in dictionary.items(): # Iterates through the dictionary's entries to convert
        encoded_entry = key.encode() + b'\x00' + b'\x00'.join(v.encode() for v in values) # Very very big boy code for formatting dictionary entry to a map entry
        entries.append(encoded_entry) # Adds the result entry to the entry list
    return b'\xa0'.join(entries) + b'\xa0' # Returns a final byte string of all entries

# As you can see I have forfeit and will not be implementing index files ;)

# Future patch should add way more efficient writing (NOT WITH INDEX FILES THIS TIME)
class mapdb: # Context manager class / Manual interaction class
    def __init__(self, filepath): # Initializes class and saves the passed filepath
        self.filepath = filepath # Predefining and saving passed filepath variable
        self.entries = {} # Predefining entries variable

    def __enter__(self): # Code to run when the context manager is entered
        self.mapfileread = open(self.filepath, "rb") # Open a mapfile from the saved filepath variable in read binary mode
        self.entries = map_to_dict(self.mapfileread.read()) # Reading the opened file and converting into a tangible version
        self.mapfileread.close() # Closes the mapfile
        return self.entries # Returns the tangible entries

    def __exit__(self, exc_type, exc_value, traceback): # Runs after all code in the context manager has ran
        mapfilewrite = open(self.filepath, 'wb+') # Open a mapfile from the saved filepath variable in write binary mode
        mapfilewrite.write(dict_to_map(self.entries)) # Writes the entries back into the file
        mapfilewrite.close() # Closes the mapfile

    # USE CONTEXT MANAGERS INSTEAD
    def push(self): # Function for pushing changes back into a mapfile without context managers
        with open(self.filepath, 'wb') as file: # Opens a mapfile from the saved filepath variable in write binary mode
            file.write(dict_to_map(self.entries)) # Writes the entries back into the file
        del self # Deletes the class object to prevent potential shadowing between file and memory

# USE CONTEXT MANAGERS INSTEAD
def pull(filepath): # Function for pulling data and converting to a tangible dictionary without context managers
    return mapdb(filepath) # Returns a mapdb object to interact with
