"""
Adapters for loading models from various sources.

All adapters are lazily imported to avoid requiring optional dependencies
unless the specific adapter is used.

Available adapters:
- HuggingFaceAdapter: Load models from HuggingFace Hub (transformers)
- VisionAdapter: Load vision models from HuggingFace, timm, torchvision
- AudioAdapter: Load audio models (Whisper, Wav2Vec2, HuBERT)
- DiffusionAdapter: Load diffusion model components (UNet, VAE, text encoder)
- MultimodalAdapter: Load multimodal models (CLIP, LLaVA, BLIP)
- LoRAAdapter: Load and merge LoRA adapters (PEFT)
- ONNXAdapter: Load and convert ONNX models
- MLXAdapter: Load MLX models for Apple Silicon
- TensorFlowAdapter: Load TensorFlow/Keras models
- JAXAdapter: Load JAX/Flax model parameters
"""

from typing import TYPE_CHECKING

# Always available - core adapter
from model_osmosis.adapters.huggingface import (
    HuggingFaceAdapter,
    HuggingFaceExpert,
    ModelModality,
    VisionExpert,
    AudioExpert,
    MultimodalExpert as HFMultimodalExpert,
)

__all__ = [
    # Core HuggingFace
    "HuggingFaceAdapter",
    "HuggingFaceExpert",
    "ModelModality",
    "VisionExpert",
    "AudioExpert",
    "HFMultimodalExpert",
    # Lazy imports
    "VisionAdapter",
    "AudioAdapter",
    "DiffusionAdapter",
    "MultimodalAdapter",
    "LoRAAdapter",
    "ONNXAdapter",
    "MLXAdapter",
    "TensorFlowAdapter",
    "JAXAdapter",
    # Expert classes
    "DiffusionUNetExpert",
    "TextEncoderExpert",
    "MultimodalExpert",
    "LoRAExpert",
    "ONNXExpert",
    "MLXExpert",
    "TensorFlowExpert",
    "JAXExpert",
]

# Type hints for lazy imports
if TYPE_CHECKING:
    from model_osmosis.adapters.vision import VisionAdapter
    from model_osmosis.adapters.audio import AudioAdapter
    from model_osmosis.adapters.diffusion import (
        DiffusionAdapter,
        DiffusionUNetExpert,
        TextEncoderExpert,
    )
    from model_osmosis.adapters.multimodal import (
        MultimodalAdapter,
        MultimodalExpert,
    )
    from model_osmosis.adapters.lora import LoRAAdapter, LoRAExpert
    from model_osmosis.adapters.onnx import ONNXAdapter, ONNXExpert
    from model_osmosis.adapters.mlx import MLXAdapter, MLXExpert
    from model_osmosis.adapters.tensorflow import TensorFlowAdapter, TensorFlowExpert
    from model_osmosis.adapters.jax import JAXAdapter, JAXExpert


def __getattr__(name: str):
    """Lazy import adapters to avoid requiring optional dependencies."""

    # Vision adapter (requires timm or torchvision optionally)
    if name == "VisionAdapter":
        from model_osmosis.adapters.vision import VisionAdapter
        return VisionAdapter

    # Audio adapter (requires transformers)
    if name == "AudioAdapter":
        from model_osmosis.adapters.audio import AudioAdapter
        return AudioAdapter

    # Diffusion adapter (requires diffusers)
    if name == "DiffusionAdapter":
        from model_osmosis.adapters.diffusion import DiffusionAdapter
        return DiffusionAdapter
    if name == "DiffusionUNetExpert":
        from model_osmosis.adapters.diffusion import DiffusionUNetExpert
        return DiffusionUNetExpert
    if name == "TextEncoderExpert":
        from model_osmosis.adapters.diffusion import TextEncoderExpert
        return TextEncoderExpert

    # Multimodal adapter (requires transformers)
    if name == "MultimodalAdapter":
        from model_osmosis.adapters.multimodal import MultimodalAdapter
        return MultimodalAdapter
    if name == "MultimodalExpert":
        from model_osmosis.adapters.multimodal import MultimodalExpert
        return MultimodalExpert

    # LoRA adapter (requires peft)
    if name == "LoRAAdapter":
        from model_osmosis.adapters.lora import LoRAAdapter
        return LoRAAdapter
    if name == "LoRAExpert":
        from model_osmosis.adapters.lora import LoRAExpert
        return LoRAExpert

    # ONNX adapter (requires onnxruntime)
    if name == "ONNXAdapter":
        from model_osmosis.adapters.onnx import ONNXAdapter
        return ONNXAdapter
    if name == "ONNXExpert":
        from model_osmosis.adapters.onnx import ONNXExpert
        return ONNXExpert

    # MLX adapter (requires mlx, Apple Silicon only)
    if name == "MLXAdapter":
        from model_osmosis.adapters.mlx import MLXAdapter
        return MLXAdapter
    if name == "MLXExpert":
        from model_osmosis.adapters.mlx import MLXExpert
        return MLXExpert

    # TensorFlow adapter (requires tensorflow)
    if name == "TensorFlowAdapter":
        from model_osmosis.adapters.tensorflow import TensorFlowAdapter
        return TensorFlowAdapter
    if name == "TensorFlowExpert":
        from model_osmosis.adapters.tensorflow import TensorFlowExpert
        return TensorFlowExpert

    # JAX adapter (requires jax)
    if name == "JAXAdapter":
        from model_osmosis.adapters.jax import JAXAdapter
        return JAXAdapter
    if name == "JAXExpert":
        from model_osmosis.adapters.jax import JAXExpert
        return JAXExpert

    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

