from __future__ import annotations

import json

try:
    from .loop_nodes import ANY_TYPE
    from .camera_config import (
        build_camera_config_json,
        build_camera_orbit_config_json,
        build_qwen_camera_config_json,
        camera_angle_choices,
        camera_detail_choices,
        camera_distance_choices,
        camera_lens_choices,
        camera_mode_choices,
        camera_orbit_focus_choices,
        camera_orbit_framing_choices,
        camera_orientation_choices,
        camera_phone_choices,
        camera_priority_choices,
        camera_shot_choices,
    )
except ImportError:  # Allows local smoke tests from the repository root.
    from loop_nodes import ANY_TYPE
    from camera_config import (
        build_camera_config_json,
        build_camera_orbit_config_json,
        build_qwen_camera_config_json,
        camera_angle_choices,
        camera_detail_choices,
        camera_distance_choices,
        camera_lens_choices,
        camera_mode_choices,
        camera_orbit_focus_choices,
        camera_orbit_framing_choices,
        camera_orientation_choices,
        camera_phone_choices,
        camera_priority_choices,
        camera_shot_choices,
    )


SXCP_CAMERA_CONFIG = "SXCP_CAMERA_CONFIG"


class SxCPCameraControl:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "camera_mode": (camera_mode_choices(), {"default": "handheld_selfie"}),
                "shot_size": (camera_shot_choices(), {"default": "auto"}),
                "angle": (camera_angle_choices(), {"default": "auto"}),
                "lens": (camera_lens_choices(), {"default": "smartphone_wide"}),
                "distance": (camera_distance_choices(), {"default": "arm_length"}),
                "orientation": (camera_orientation_choices(), {"default": "vertical_story"}),
                "phone_visibility": (camera_phone_choices(), {"default": "phone_visible"}),
                "priority": (camera_priority_choices(), {"default": "locked"}),
                "camera_detail": (camera_detail_choices(), {"default": "compact"}),
            }
        }

    RETURN_TYPES = (SXCP_CAMERA_CONFIG,)
    RETURN_NAMES = ("camera_config",)
    FUNCTION = "build"
    CATEGORY = "prompt_builder"

    def build(
        self,
        camera_mode,
        shot_size,
        angle,
        lens,
        distance,
        orientation,
        phone_visibility,
        priority,
        camera_detail,
    ):
        return (
            build_camera_config_json(
                camera_mode=camera_mode,
                shot_size=shot_size,
                angle=angle,
                lens=lens,
                distance=distance,
                orientation=orientation,
                phone_visibility=phone_visibility,
                priority=priority,
                camera_detail=camera_detail,
            ),
        )


class SxCPCameraOrbitControl:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "enabled": ("BOOLEAN", {"default": True}),
                "camera_mode": (camera_mode_choices(), {"default": "standard"}),
                "horizontal_angle": ("INT", {"default": 0, "min": 0, "max": 359, "step": 1}),
                "vertical_angle": ("INT", {"default": 0, "min": -90, "max": 90, "step": 1}),
                "zoom": ("FLOAT", {"default": 5.0, "min": 0.0, "max": 10.0, "step": 0.1}),
                "framing": (camera_orbit_framing_choices(), {"default": "from_zoom"}),
                "subject_focus": (camera_orbit_focus_choices(), {"default": "auto"}),
                "lens": (camera_lens_choices(), {"default": "auto"}),
                "orientation": (camera_orientation_choices(), {"default": "auto"}),
                "phone_visibility": (camera_phone_choices(), {"default": "auto"}),
                "priority": (camera_priority_choices(), {"default": "locked"}),
                "camera_detail": (camera_detail_choices(), {"default": "compact"}),
                "include_degrees": ("BOOLEAN", {"default": True}),
            }
        }

    RETURN_TYPES = (SXCP_CAMERA_CONFIG, "STRING", "STRING")
    RETURN_NAMES = ("camera_config", "camera_prompt", "camera_info_json")
    FUNCTION = "build"
    CATEGORY = "prompt_builder"

    def build(
        self,
        enabled,
        camera_mode,
        horizontal_angle,
        vertical_angle,
        zoom,
        framing,
        subject_focus,
        lens,
        orientation,
        phone_visibility,
        priority,
        camera_detail,
        include_degrees,
    ):
        config = build_camera_orbit_config_json(
            enabled=enabled,
            camera_mode=camera_mode,
            horizontal_angle=horizontal_angle,
            vertical_angle=vertical_angle,
            zoom=zoom,
            framing=framing,
            subject_focus=subject_focus,
            lens=lens,
            orientation=orientation,
            phone_visibility=phone_visibility,
            priority=priority,
            camera_detail=camera_detail,
            include_degrees=include_degrees,
        )
        parsed = json.loads(config)
        camera_prompt = parsed.get("custom_camera_prompt", "")
        return config, camera_prompt, json.dumps(parsed, ensure_ascii=True, sort_keys=True)


class SxCPQwenCameraTranslator:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "qwen_prompt": ("STRING", {"default": ""}),
                "prefer_camera_info": ("BOOLEAN", {"default": True}),
                "camera_mode": (camera_mode_choices(), {"default": "standard"}),
                "subject_focus": (camera_orbit_focus_choices(), {"default": "auto"}),
                "lens": (camera_lens_choices(), {"default": "auto"}),
                "orientation": (camera_orientation_choices(), {"default": "auto"}),
                "phone_visibility": (camera_phone_choices(), {"default": "auto"}),
                "priority": (camera_priority_choices(), {"default": "locked"}),
                "camera_detail": (camera_detail_choices(), {"default": "compact"}),
                "include_degrees": ("BOOLEAN", {"default": False}),
                "suppress_phone_visibility": ("BOOLEAN", {"default": True}),
            },
            "optional": {
                "camera_info": (ANY_TYPE,),
            },
        }

    RETURN_TYPES = (SXCP_CAMERA_CONFIG, "STRING", "STRING")
    RETURN_NAMES = ("camera_config", "camera_prompt", "camera_info_json")
    FUNCTION = "build"
    CATEGORY = "prompt_builder"

    def build(
        self,
        qwen_prompt,
        prefer_camera_info,
        camera_mode,
        subject_focus,
        lens,
        orientation,
        phone_visibility,
        priority,
        camera_detail,
        include_degrees,
        suppress_phone_visibility,
        camera_info=None,
    ):
        config = build_qwen_camera_config_json(
            qwen_prompt=qwen_prompt or "",
            camera_info=camera_info,
            prefer_camera_info=prefer_camera_info,
            camera_mode=camera_mode,
            subject_focus=subject_focus,
            lens=lens,
            orientation=orientation,
            phone_visibility=phone_visibility,
            priority=priority,
            camera_detail=camera_detail,
            include_degrees=include_degrees,
            suppress_phone_visibility=suppress_phone_visibility,
        )
        parsed = json.loads(config)
        camera_prompt = parsed.get("custom_camera_prompt", "")
        return config, camera_prompt, json.dumps(parsed, ensure_ascii=True, sort_keys=True)


NODE_CLASS_MAPPINGS = {
    "SxCPCameraControl": SxCPCameraControl,
    "SxCPCameraOrbitControl": SxCPCameraOrbitControl,
    "SxCPQwenCameraTranslator": SxCPQwenCameraTranslator,
}

NODE_DISPLAY_NAME_MAPPINGS = {
    "SxCPCameraControl": "SxCP Camera Control",
    "SxCPCameraOrbitControl": "SxCP Camera Orbit Control",
    "SxCPQwenCameraTranslator": "SxCP Qwen Camera Translator",
}
