# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/51_ssrc.ipynb.

# %% auto 0
__all__ = ['StructuredSrc', 'StructuredPath', 'StructuredFile', 'StructuredDir']

# %% ../nbs/51_ssrc.ipynb 5
import os
from pathlib import Path

# %% ../nbs/51_ssrc.ipynb 7
from atyp import (StrQ,)

from nchr import DOT
from nlit import (BASE, LEAF, PATH, NAME, PathKind, ABRV, DESC, REQUIRED)

from chck.path import ispath
from pstr.util import toprivate

# %% ../nbs/51_ssrc.ipynb 9
from .util import aspath
from .leaf import trimleaf, joinleaf, normleaf
from .plib import PLib
from .srcs import Src, PathSrc, FileSrc, DirSrc, TREEKWS

# %% ../nbs/51_ssrc.ipynb 11
_BASE, _LEAF, _PATH = tuple(map(toprivate, (BASE, LEAF, PATH)))

# %% ../nbs/51_ssrc.ipynb 12
class StructuredSrc(Src):
    required: bool = True
    aspec: tuple = (PATH, NAME, ABRV, DESC, TREEKWS, LEAF, BASE, REQUIRED)
    
    @property
    def optional(self) -> bool: return not self.required
    @optional.setter
    def optional(self, bval: bool): self.required = not bool(bval)

    @property
    def leaf(self) -> Path: return getattr(self, _LEAF, Path(DOT))
    @leaf.setter
    def leaf(self, leaf: Path):
        self._leaf = aspath(leaf)
        self.base = trimleaf(self.path, self.leaf) # Update base to respect new leaf
        self.path = joinleaf(self.path, self.leaf) # Recompute path = base / leaf

    @property
    def base(self) -> Path: return getattr(self, _BASE, Path(DOT))
    @base.setter
    def base(self, path: Path):
        self._base = trimleaf(path, self.leaf)      # Ensure base doesn't include leaf
        self._path = joinleaf(self.base, self.leaf) # Recompute path = base / leaf

    @property
    def path(self) -> Path: return getattr(self, _PATH, Path(DOT))
    @path.setter
    def path(self, path: str):
        path, leaf = normleaf(path, self.leaf)
        self._base = trimleaf(path, self.leaf)
        self._path = joinleaf(self.base, self.leaf)

    def isvalid(self) -> bool:
        return self.exists() if self.required else True

    def canbechild(self, other: str) -> bool: 
        return False if self.kind == str(PathKind.FILE) else True
    
    def canbeparent(self, other: str) -> bool:
        otype = other.kind if isinstance(other, type(self)) else str(PathKind.PATH)
        return False if otype == str(PathKind.FILE) else True
    
    def __truediv__(self, other):
        if self.canbeparent(other): return super().__truediv__(other)
        raise ValueError(f'{self.name} cannot be parent of {other}')

    def __rtruediv__(self, other):
        if self.canbechild(other): return super().__rtruediv__(other)
        raise ValueError(f'{self.name} cannot be child of {other}')
    
    def __init__(self, path: StrQ = None, leaf: StrQ = None, *args, **kwargs):
        base, leaf = normleaf(path, leaf or self.leaf)
        self.leaf = leaf
        self.base = trimleaf(base, leaf)
        self.path = joinleaf(self.base, self.leaf)
        
        kwargs.update(leaf=leaf, base=base)
        super().__init__(self.path, *args, **kwargs)

# %% ../nbs/51_ssrc.ipynb 14
class StructuredPath(StructuredSrc):
    ...

# %% ../nbs/51_ssrc.ipynb 16
class StructuredFile(StructuredSrc):
    file: str = FileSrc('')    
    ptype: PathKind = PathKind.FILE
    
    @property
    def filename(self): 
        return self.file.name if ispath(self.file) or hasattr(self, NAME) else self.file

# %% ../nbs/51_ssrc.ipynb 18
class StructuredDir(StructuredSrc):
    dir: str = DirSrc('')
    ptype: PathKind = PathKind.DIR
    entries: tuple[StructuredSrc, ...]
    
    @property
    def dirname(self): return self.dir.name

    def isvalid(self) -> bool: 
        return all(e.isvalid() for e in self.entries) if self.required else True
