"""Memory mixin for MCGhidra.

Provides tools for memory read/write operations.
"""

from typing import Any, Dict, Optional

from fastmcp.contrib.mcp_mixin import mcp_tool

from .base import MCGhidraMixinBase


class MemoryMixin(MCGhidraMixinBase):
    """Mixin for memory operations.

    Provides tools for:
    - Reading memory bytes
    - Writing memory bytes (use with caution)
    """

    @mcp_tool()
    def memory_read(
        self,
        address: str,
        length: int = 16,
        format: str = "hex",
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Read bytes from memory.

        Args:
            address: Memory address in hex format
            length: Number of bytes to read (default: 16)
            format: Output format - "hex", "base64", or "string" (default: "hex")
            port: Ghidra instance port (optional)

        Returns:
            Memory contents in the requested format
        """
        if not address:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "Address parameter is required",
                },
            }

        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"success": False, "error": {"code": "NO_INSTANCE", "message": str(e)}}

        params = {
            "address": address,
            "length": length,
            "format": format,
        }

        response = self.safe_get(port, "memory", params)
        simplified = self.simplify_response(response)

        if "result" in simplified and isinstance(simplified["result"], dict):
            result = simplified["result"]
            memory_info = {
                "success": True,
                "address": result.get("address", address),
                "length": result.get("bytesRead", length),
                "format": format,
            }

            if "hexBytes" in result:
                memory_info["hexBytes"] = result["hexBytes"]
            if "rawBytes" in result:
                memory_info["rawBytes"] = result["rawBytes"]

            return memory_info

        return simplified

    @mcp_tool()
    def memory_write(
        self,
        address: str,
        bytes_data: str,
        format: str = "hex",
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Write bytes to memory (use with caution).

        Args:
            address: Memory address in hex format
            bytes_data: Data to write (format depends on 'format' parameter)
            format: Input format - "hex", "base64", or "string" (default: "hex")
            port: Ghidra instance port (optional)

        Returns:
            Operation result
        """
        if not address:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "Address parameter is required",
                },
            }

        if not bytes_data:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "Bytes parameter is required",
                },
            }

        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"success": False, "error": {"code": "NO_INSTANCE", "message": str(e)}}

        payload = {
            "bytes": bytes_data,
            "format": format,
        }

        response = self.safe_patch(port, f"programs/current/memory/{address}", payload)
        return self.simplify_response(response)
