import os
from huggingface_hub import repo_exists
from .aimv2_encoder import AIMv2VisionTower
from .clip_encoder import CLIPVisionTower, CLIPVisionTowerS2
from .dinov2_encoder import DINOv2VisionTower
from .general_encoder import GeneralVisionTower
from .openclip_encoder import OpenCLIPVisionTower
from .radio_encoder import RADIOVisionTower
from .siglip_encoder import SigLIPVisionTower
from .timm_encoder import TimmModelVisionTower

def build_vision_tower(vision_tower_cfg, **kwargs):
    vision_tower = getattr(vision_tower_cfg, 'mm_vision_tower', getattr(vision_tower_cfg, 'vision_tower', None))
    is_absolute_path_exists = os.path.exists(vision_tower)
    use_s2 = getattr(vision_tower_cfg, 's2', False)
    if 'radio' in vision_tower:
        if use_s2:
            raise ValueError(f'RADIOVisionTower does not support S2 scales')
        return RADIOVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
    elif is_absolute_path_exists or repo_exists(vision_tower) or "ShareGPT4V" in vision_tower:
        if 'DVT/voc_distilled/' in vision_tower:
            if use_s2:
                raise ValueError(f'TimmModelVisionTower does not support S2 scales')
            vision_tower_name = vision_tower.split('DVT/voc_distilled/')[-1]
            return TimmModelVisionTower(vision_tower_name, args=vision_tower_cfg, ckpt_path=vision_tower,**kwargs)
        elif 'convnext' in vision_tower:
            if use_s2:
                raise ValueError(f'OpenCLIPVisionTower does not support S2 scales')
            return OpenCLIPVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        elif 'timm' in vision_tower:
            if use_s2:
                raise ValueError(f'TimmModelVisionTower does not support S2 scales')
            return TimmModelVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        elif 'aimv2' in vision_tower:
            if use_s2:
                raise ValueError(f'AIMv2VisionTower does not support S2 scales')
            return AIMv2VisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        elif 'siglip' in vision_tower:
            if use_s2:
                raise ValueError(f'SigLIPVisionTower does not support S2 scales')
            return SigLIPVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        elif 'clip' in vision_tower and 'convnext' not in vision_tower:
            if use_s2:
                return CLIPVisionTowerS2(vision_tower, args=vision_tower_cfg, **kwargs)
            else:
                return CLIPVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        elif 'dinov2' in vision_tower:
            if use_s2:
                raise ValueError(f'DINOv2VisionTower does not support S2 scales')
            return DINOv2VisionTower(vision_tower, args=vision_tower_cfg, **kwargs)
        else:
            if use_s2:
                raise ValueError(f'GeneralVisionTower does not support S2 scales')
            return GeneralVisionTower(vision_tower, args=vision_tower_cfg, **kwargs)

    raise ValueError(f'Unknown vision tower: {vision_tower}')
