# Path: DnD/modules/lib/exceptionsLib.py
# class OverflowSpells(SpellError):
#     def __init__(self, spell):
#         self.spell = spell
# 
#     def __str__(self):
#         formatstr = 'You have full spell slots of level {lv} already.'
#         return formatstr.format(lv=self.spell.level)
# 
# class OutOfSpells(SpellError):
#     def __init__(self, spell):
#         self.spell = spell
# 
#     def __str__(self):
#         formatstr = 'You have no spell slots of level {lv} remaining.'
#         return formatstr.format(lv=(self.spell if isinstance(self.spell, int)
#                                     else self.spell.level))
# 
# class AlreadyPrepared(SpellError):
#     pass
# 
# Path: DnD/modules/lib/helpers.py
# def sanitize_filename(name: str) -> str:
#     """Translates problematic characters in a filename into happier ones."""
#     return name.translate(str.maketrans(" '/:", "_@&$"))
# 
# Path: DnD/modules/lib/interface.py
# class DataInterface:
#     class JsonPointerCache:
#         def __init__(self):
#             self.cache = {}
# 
#         def __getitem__(self, key: str) -> jsonpointer.JsonPointer:
#             if key not in self.cache:
#                 self.cache[key] = jsonpointer.JsonPointer(key)
#             return self.cache[key]
# 
#     def __init__(self, data: Union[list, Dict[str, Any]], readonly=False, basepath=""):
#         self.data = data
#         self.basepath = basepath.rstrip('/')
#         self.readonly = readonly
#         self._cache = type(self).JsonPointerCache()
# 
#     def __iter__(self):
#         obj = self.get('/')
#         if isinstance(obj, dict):
#             yield from obj.items()
#         elif isinstance(obj, list):
#             yield from obj
# 
#     def get(self, path: str):
#         if self.basepath + path == '/':
#             return self.data
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         return pointer.resolve(self.data, None)
# 
#     def delete(self, path):
#         if self.readonly:
#             raise ex.ReadonlyError('{} is readonly'.format(self.data))
#         if self.basepath + path == '/':
#             self.data = {}
#             return
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         subdoc, key = pointer.to_last(self.data)
#         del subdoc[key]
# 
#     def set(self, path, value):
#         if self.readonly:
#             raise ex.ReadonlyError('{} is readonly'.format(self.data))
#         if self.basepath + path == '/':
#             self.data = value
#             return
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         pointer.set(self.data, value)
# 
#     def cd(self, path, readonly=False):
#         return DataInterface(self.data, readonly=self.readonly or readonly,
#                              basepath=self.basepath + path)
# 
# class JsonInterface(DataInterface):
#     OBJECTSPATH = Path('./objects/')
#     EXTANT = {}
# 
#     def __new__(cls, filename, **kwargs):
#         if kwargs.get('isabsolute', False):
#             totalpath = filename
#         else:
#             totalpath = cls.OBJECTSPATH / filename
#         if totalpath in cls.EXTANT:
#             return cls.EXTANT[totalpath]
#         else:
#             obj = super().__new__(cls)
#             return obj
# 
#     def __init__(self, filename, readonly=False, isabsolute=False):
#         self.shortFilename = h.readable_filename(str(filename))
#         if isabsolute:
#             self.filename = Path(filename)
#         else:
#             self.filename = self.OBJECTSPATH / filename
#         with self.filename.open('r') as f:
#             data = json.load(f, object_pairs_hook=collections.OrderedDict)
#             super().__init__(data, readonly)
#         self.EXTANT[self.filename] = self
# 
#     def __add__(self, other):
#         if isinstance(other, JsonInterface):
#             return LinkedInterface(self, other)
#         elif isinstance(other, LinkedInterface):
#             return other.__add__(self)
#         else:
#             raise TypeError("You can only add a JsonInterface or a "
#                             "MultiInterface to a JsonInterface")
# 
#     def __repr__(self):
#         return "<JsonInterface to {}>".format(self.filename)
# 
#     def __str__(self):
#         return self.shortFilename
# 
#     def write(self):
#         if self.readonly:
#             raise ex.ReadonlyError("Trying to write a readonly file")
#         with open(self.filename, 'w') as f:
#             json.dump(self.data, f, indent=2)
# 
# Path: DnD/modules/lib/settingsLib.py
# class RestLength(enum.IntEnum):
#     LONG = 100
#     SHORT = 10
#     TURN = 1
#     NOTHING = 0
# 
#     @classmethod
#     def from_string(cls, value):
#         if value == 'long' or value == 'long rest':
#             return RestLength.LONG
#         elif value == 'short' or value == 'short rest':
#             return RestLength.SHORT
#         elif value == 'turn':
#             return RestLength.TURN
#         else:
#             return RestLength.NOTHING


from pathlib import Path
from . import characterLib as char
from . import spellLib as sp
from .exceptionsLib import OverflowSpells, OutOfSpells, AlreadyPrepared
from .helpers import sanitize_filename
from .interface import DataInterface, JsonInterface
from .settingsLib import RestLength



class SpellResource:
    def __init__(self, jf: DataInterface):
        self.record = jf

    def cast(self, level: int):
        raise NotImplementedError

    def regain(self, level: int):
        raise NotImplementedError

    def reset(self):
        raise NotImplementedError


# Path: DnD/modules/lib/exceptionsLib.py
# class OverflowSpells(SpellError):
#     def __init__(self, spell):
#         self.spell = spell
# 
#     def __str__(self):
#         formatstr = 'You have full spell slots of level {lv} already.'
#         return formatstr.format(lv=self.spell.level)
# 
# class OutOfSpells(SpellError):
#     def __init__(self, spell):
#         self.spell = spell
# 
#     def __str__(self):
#         formatstr = 'You have no spell slots of level {lv} remaining.'
#         return formatstr.format(lv=(self.spell if isinstance(self.spell, int)
#                                     else self.spell.level))
# 
# class AlreadyPrepared(SpellError):
#     pass
# 
# Path: DnD/modules/lib/helpers.py
# def sanitize_filename(name: str) -> str:
#     """Translates problematic characters in a filename into happier ones."""
#     return name.translate(str.maketrans(" '/:", "_@&$"))
# 
# Path: DnD/modules/lib/interface.py
# class DataInterface:
#     class JsonPointerCache:
#         def __init__(self):
#             self.cache = {}
# 
#         def __getitem__(self, key: str) -> jsonpointer.JsonPointer:
#             if key not in self.cache:
#                 self.cache[key] = jsonpointer.JsonPointer(key)
#             return self.cache[key]
# 
#     def __init__(self, data: Union[list, Dict[str, Any]], readonly=False, basepath=""):
#         self.data = data
#         self.basepath = basepath.rstrip('/')
#         self.readonly = readonly
#         self._cache = type(self).JsonPointerCache()
# 
#     def __iter__(self):
#         obj = self.get('/')
#         if isinstance(obj, dict):
#             yield from obj.items()
#         elif isinstance(obj, list):
#             yield from obj
# 
#     def get(self, path: str):
#         if self.basepath + path == '/':
#             return self.data
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         return pointer.resolve(self.data, None)
# 
#     def delete(self, path):
#         if self.readonly:
#             raise ex.ReadonlyError('{} is readonly'.format(self.data))
#         if self.basepath + path == '/':
#             self.data = {}
#             return
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         subdoc, key = pointer.to_last(self.data)
#         del subdoc[key]
# 
#     def set(self, path, value):
#         if self.readonly:
#             raise ex.ReadonlyError('{} is readonly'.format(self.data))
#         if self.basepath + path == '/':
#             self.data = value
#             return
#         if path == '/':
#             path = ''
#         pointer = self._cache[self.basepath + path]
#         pointer.set(self.data, value)
# 
#     def cd(self, path, readonly=False):
#         return DataInterface(self.data, readonly=self.readonly or readonly,
#                              basepath=self.basepath + path)
# 
# class JsonInterface(DataInterface):
#     OBJECTSPATH = Path('./objects/')
#     EXTANT = {}
# 
#     def __new__(cls, filename, **kwargs):
#         if kwargs.get('isabsolute', False):
#             totalpath = filename
#         else:
#             totalpath = cls.OBJECTSPATH / filename
#         if totalpath in cls.EXTANT:
#             return cls.EXTANT[totalpath]
#         else:
#             obj = super().__new__(cls)
#             return obj
# 
#     def __init__(self, filename, readonly=False, isabsolute=False):
#         self.shortFilename = h.readable_filename(str(filename))
#         if isabsolute:
#             self.filename = Path(filename)
#         else:
#             self.filename = self.OBJECTSPATH / filename
#         with self.filename.open('r') as f:
#             data = json.load(f, object_pairs_hook=collections.OrderedDict)
#             super().__init__(data, readonly)
#         self.EXTANT[self.filename] = self
# 
#     def __add__(self, other):
#         if isinstance(other, JsonInterface):
#             return LinkedInterface(self, other)
#         elif isinstance(other, LinkedInterface):
#             return other.__add__(self)
#         else:
#             raise TypeError("You can only add a JsonInterface or a "
#                             "MultiInterface to a JsonInterface")
# 
#     def __repr__(self):
#         return "<JsonInterface to {}>".format(self.filename)
# 
#     def __str__(self):
#         return self.shortFilename
# 
#     def write(self):
#         if self.readonly:
#             raise ex.ReadonlyError("Trying to write a readonly file")
#         with open(self.filename, 'w') as f:
#             json.dump(self.data, f, indent=2)
# 
# Path: DnD/modules/lib/settingsLib.py
# class RestLength(enum.IntEnum):
#     LONG = 100
#     SHORT = 10
#     TURN = 1
#     NOTHING = 0
# 
#     @classmethod
#     def from_string(cls, value):
#         if value == 'long' or value == 'long rest':
#             return RestLength.LONG
#         elif value == 'short' or value == 'short rest':
#             return RestLength.SHORT
#         elif value == 'turn':
#             return RestLength.TURN
#         else:
#             return RestLength.NOTHING


# Path: DnD/modules/lib/spellcastingLib.py
from pathlib import Path
from . import characterLib as char
from . import spellLib as sp
from .exceptionsLib import OverflowSpells, OutOfSpells, AlreadyPrepared
from .helpers import sanitize_filename
from .interface import DataInterface, JsonInterface
from .settingsLib import RestLength




class SpellResource:
    def __init__(self, jf: DataInterface):
        self.record = jf

    def cast(self, level: int):
        raise NotImplementedError

    def regain(self, level: int):
        raise NotImplementedError

    def reset(self):
        raise NotImplementedError


    def rest(self, length: RestLength):