"""Segments mixin for MCGhidra.

Provides tools for querying memory segments (sections) and their permissions.
"""

from typing import Any, Dict, List, Optional

from fastmcp import Context
from fastmcp.contrib.mcp_mixin import mcp_resource, mcp_tool

from ..config import get_config
from .base import MCGhidraMixinBase


class SegmentsMixin(MCGhidraMixinBase):
    """Mixin for memory segment operations.

    Provides tools for:
    - Listing memory segments with permissions and size info
    """

    @mcp_tool()
    def segments_list(
        self,
        name: Optional[str] = None,
        port: Optional[int] = None,
        page_size: int = 50,
        grep: Optional[str] = None,
        grep_ignorecase: bool = True,
        return_all: bool = False,
        fields: Optional[List[str]] = None,
        ctx: Optional[Context] = None,
    ) -> Dict[str, Any]:
        """List memory segments with R/W/X permissions and size info.

        Args:
            name: Filter by segment name (server-side, exact match)
            port: Ghidra instance port (optional)
            page_size: Segments per page (default: 50, max: 500)
            grep: Regex pattern to filter segment names
            grep_ignorecase: Case-insensitive grep (default: True)
            return_all: Return all segments without pagination
            fields: Field names to keep (e.g. ['name', 'start', 'permissions']). Reduces response size.
            ctx: FastMCP context (auto-injected)

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

        config = get_config()
        cap = config.resource_caps.get("segments", 500)
        params = {"limit": cap}
        if name:
            params["name"] = name

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

        if not simplified.get("success", True):
            return simplified

        segments = simplified.get("result", [])
        if not isinstance(segments, list):
            segments = []

        query_params = {"tool": "segments_list", "port": port, "name": name, "grep": grep}
        session_id = self._get_session_id(ctx)

        return self.filtered_paginate(
            data=segments,
            query_params=query_params,
            tool_name="segments_list",
            session_id=session_id,
            page_size=min(page_size, config.max_page_size),
            grep=grep,
            grep_ignorecase=grep_ignorecase,
            return_all=return_all,
            fields=fields,
        )

    # Resources

    @mcp_resource(uri="ghidra://instance/{port}/segments")
    def resource_segments_list(self, port: Optional[int] = None) -> Dict[str, Any]:
        """MCP Resource: List memory segments (capped).

        Args:
            port: Ghidra instance port

        Returns:
            List of memory segments (capped)
        """
        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"error": str(e)}

        config = get_config()
        cap = config.resource_caps.get("segments", 500)

        response = self.safe_get(port, "segments", {"limit": cap})
        simplified = self.simplify_response(response)

        if not simplified.get("success", True):
            return simplified

        segments = simplified.get("result", [])
        if not isinstance(segments, list):
            segments = []

        return {
            "segments": segments[:cap],
            "count": len(segments),
            "capped_at": cap if len(segments) >= cap else None,
            "_hint": "Use segments_list() tool for full pagination"
            if len(segments) >= cap
            else None,
        }
