#!/usr/bin/env python3
#exonware/xwsystem/src/exonware/xwsystem/io/common/base.py
"""
Company: eXonware.com
Author: eXonware Backend Team
Email: connect@exonware.com
Version: 0.9.0.23
Generation Date: 30-Oct-2025
Base classes and utilities for common IO operations.
Like codec/base.py, this contains:
- Abstract base classes (AAtomicWriter, APathValidator, etc.)
- Utilities and helper functions
- Registries (if needed in future)
Priority 1 (Security): Safe base implementations
Priority 2 (Usability): Easy to extend
Priority 3 (Maintainability): Clean abstractions
Priority 4 (Performance): Efficient operations
Priority 5 (Extensibility): Ready for new utilities
"""

from __future__ import annotations
from abc import ABC, abstractmethod

from collections.abc import Callable
from pathlib import Path
from ..contracts import IAtomicWriter, IPathValidator, IFileWatcher, IFileLock
from ..defs import AtomicMode, WatcherEvent, LockMode, PathSecurityLevel
__all__ = [
    'AAtomicWriter',
    'APathValidator',
    'AFileWatcher',
    'AFileLock',
]


class AAtomicWriter(IAtomicWriter, ABC):
    """
    Abstract base for atomic file writers.
    Provides skeletal implementation for atomic write operations.
    """

    def __init__(self, path: str | Path, mode: AtomicMode = AtomicMode.WRITE_BACKUP):
        """Initialize atomic writer."""
        self.path = Path(path)
        self.mode = mode
        self._temp_path: Path | None = None
        self._backup_path: Path | None = None
    @abstractmethod

    def write(self, data: bytes) -> int:
        """Write data atomically."""
        pass

    def __enter__(self) -> AAtomicWriter:
        """Enter context manager."""
        return self
    @abstractmethod

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        """Exit context manager."""
        pass


class APathValidator(IPathValidator, ABC):
    """
    Abstract base for path validators.
    Provides common validation logic.
    """

    def __init__(self, security_level: PathSecurityLevel = PathSecurityLevel.STRICT):
        """Initialize path validator."""
        self.security_level = security_level
    @abstractmethod

    def validate_path(self, path: str | Path) -> bool:
        """Validate path safety."""
        pass

    def is_safe_path(self, path: str | Path) -> bool:
        """Check if path is safe to use."""
        try:
            return self.validate_path(path)
        except Exception:
            return False

    def normalize_path(self, path: str | Path) -> Path:
        """Normalize and resolve path."""
        return Path(path).resolve()


class AFileWatcher(IFileWatcher, ABC):
    """
    Abstract base for file watchers.
    Provides common watching logic.
    """

    def __init__(self, poll_interval: float = 1.0):
        """Initialize watcher."""
        self.poll_interval = poll_interval
        self._watched = {}
        self._running = False
    @abstractmethod

    def watch(self, path: Path, on_change: Callable[[Path, str], None]) -> None:
        """Watch path for changes."""
        pass
    @abstractmethod

    def unwatch(self, path: Path) -> None:
        """Stop watching path."""
        pass
    @abstractmethod

    def start(self) -> None:
        """Start watching."""
        pass
    @abstractmethod

    def stop(self) -> None:
        """Stop all watchers."""
        pass


class AFileLock(IFileLock, ABC):
    """
    Abstract base for file locks.
    Provides common locking logic.
    """

    def __init__(self, path: str | Path, mode: LockMode = LockMode.EXCLUSIVE):
        """Initialize lock."""
        self.path = Path(path)
        self.mode = mode
        self._locked = False
    @abstractmethod

    def acquire(self, timeout: float | None = None) -> bool:
        """Acquire lock."""
        pass
    @abstractmethod

    def release(self) -> None:
        """Release lock."""
        pass

    def is_locked(self) -> bool:
        """Check if locked."""
        return self._locked

    def __enter__(self) -> AFileLock:
        """Context manager entry."""
        self.acquire()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        """Context manager exit."""
        self.release()
