"""@package docstring
B-ASIC Utils Module.
This module contains functions that are used as utilities by other modules or by the user.
"""

from typing import Optional
from os import getcwd, path

from b_asic import AbstractOperation

import dill  # Used instead of pickle to support serializing lambda functions


def save_structure(struct: AbstractOperation, _path: Optional[str] = None, _name: Optional[str] = None) -> str: 
    """Saves the structure to a specific path using the pickle module.
    Returns the path to the struct if save succeeds.
    
    Arguments:
    struct: The structure to save.

    Keyword Arguments:
    _path: The path (str) to which the structure will be saved.
    _name: The name (str) of the file to be saved. Only used if _path is None.
    """
    try:
        if _path is None:
            _name = _name if _name is not None else f"{struct.type_name}.pickle"
            _path = path.join(getcwd(), _name)

            index = 1
            while path.exists(_path):
                _path = path.join(getcwd(), f"{struct.type_name}({index}).pickle")
                index += 1

        with open(_path, "wb") as handle:
            dill.dump(struct, handle, protocol=dill.HIGHEST_PROTOCOL)
    except Exception as e:
        print("Unexpected error occured while saving structure: ", e)
        return None
    
    return _path

def load_structure(_path: str) -> AbstractOperation:
    """Saves the structure to a specific path using the pickle module.
    Returns the struct that was loaded from the path.

    Keyword Arguments:
    path: The path to which the structure will be loaded from.
    """
    try:
        with open(_path, "rb") as handle:
            return dill.load(handle)
    except Exception as e:
        print("Unexpected error occured while loading structure: ", e)
    
    return None