# Generated by Copilot
# Maintained by Dinesh Kumar C (https://github.com/Dinesh210805/blender-mcp)
# Forked from original work by Siddharth Ahuja (https://github.com/ahujasid/blender-mcp)

"""Base tool functionality for Blender MCP."""

import time
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from functools import wraps

from ..connection import execute_blender_command
from ..utils import get_logger, log_tool_call, log_tool_result
from ..exceptions import BlenderMCPError


def tool_wrapper(func):
    """Decorator for tool functions to add logging and error handling."""
    @wraps(func)
    def wrapper(*args, **kwargs):
        logger = get_logger("Tools")
        tool_name = func.__name__
        
        start_time = time.time()
        
        try:
            log_tool_call(logger, tool_name, kwargs)
            result = func(*args, **kwargs)
            
            duration = time.time() - start_time
            log_tool_result(logger, tool_name, True, duration)
            
            return result
            
        except BlenderMCPError as e:
            duration = time.time() - start_time
            log_tool_result(logger, tool_name, False, duration)
            logger.error(f"Tool {tool_name} failed: {e.message}")
            return f"Error: {e.message}"
            
        except Exception as e:
            duration = time.time() - start_time
            log_tool_result(logger, tool_name, False, duration)
            logger.exception(f"Unexpected error in tool {tool_name}")
            return f"Unexpected error: {str(e)}"
    
    return wrapper


class BaseTool(ABC):
    """Base class for Blender MCP tools."""
    
    def __init__(self):
        self.logger = get_logger(f"Tools.{self.__class__.__name__}")
    
    @abstractmethod
    def execute(self, **kwargs) -> Any:
        """Execute the tool with given parameters."""
        pass
    
    def send_command(self, command_type: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """Send command to Blender."""
        return execute_blender_command(command_type, params)
