///| Resource Registry - Internal resource management

///|
priv struct ResourceEntry {
  definition : @types.ResourceDefinition
  handler : async (@runtime.RequestContext, Json) -> Result[
    @resource.ResourceReadOutcome,
    @types.MCPError,
  ]
}

///|
struct ResourceRegistry {
  resources : Map[String, ResourceEntry]
  templates : Map[String, @types.ResourceTemplateDefinition]
}

///|
fn ResourceRegistry::ResourceRegistry() -> ResourceRegistry {
  { resources: Default::default(), templates: Default::default(), }
}

///|
fn ResourceRegistry::register(
  self : ResourceRegistry,
  uri : String,
  name : String,
  description : String,
  mime_type : String,
  handler : async (@runtime.RequestContext, Json) -> Result[
    @resource.ResourceReadOutcome,
    @types.MCPError,
  ],
) -> Unit {
  self.register_definition(
    @types.ResourceDefinition::new(uri, name, description~, mime_type~),
    handler,
  )
}

///|
fn ResourceRegistry::register_definition(
  self : ResourceRegistry,
  definition : @types.ResourceDefinition,
  handler : async (@runtime.RequestContext, Json) -> Result[
    @resource.ResourceReadOutcome,
    @types.MCPError,
  ],
) -> Unit {
  self.resources.set(definition.uri, { definition, handler, })
}

///|
fn ResourceRegistry::register_simple(
  self : ResourceRegistry,
  uri : String,
  name : String,
  description : String,
  mime_type : String,
  handler : async (@runtime.RequestContext) -> Result[
    @resource.ResourceReadResult,
    @types.MCPError,
  ],
) -> Unit {
  let wrapped = async fn(
    context : @runtime.RequestContext,
    _params : Json,
  ) -> Result[@resource.ResourceReadOutcome, @types.MCPError] {
    match handler(context) {
      Ok(result) => Ok(@resource.ResourceReadOutcome::Complete(result))
      Err(e) => Err(e)
    }
  }
  self.register(uri, name, description, mime_type, wrapped)
}

///|
fn[T : @resource.Resource] ResourceRegistry::register_trait_resource(
  self : ResourceRegistry,
  resource : T,
) -> Unit {
  let name = resource.name()
  let description = resource.description()
  let uri = resource.uri()
  let mime_type = resource.mime_type()
  let handler = async fn(
    context : @runtime.RequestContext,
    _params : Json,
  ) -> Result[@resource.ResourceReadOutcome, @types.MCPError] {
    match resource.read(context) {
      Ok(result) => Ok(@resource.ResourceReadOutcome::Complete(result))
      Err(e) => Err(e)
    }
  }
  self.register(uri, name, description, mime_type, handler)
}

///|
fn[T : @resource.ResourceMRTR] ResourceRegistry::register_trait_resource_mrtr(
  self : ResourceRegistry,
  resource : T,
) -> Unit {
  let name = resource.name()
  let description = resource.description()
  let uri = resource.uri()
  let mime_type = resource.mime_type()
  let handler = async fn(
    context : @runtime.RequestContext,
    params : Json,
  ) -> Result[@resource.ResourceReadOutcome, @types.MCPError] {
    resource.read(context, params)
  }
  self.register(uri, name, description, mime_type, handler)
}

///|
fn ResourceRegistry::register_template(
  self : ResourceRegistry,
  uri_template : String,
  name : String,
  description : String?,
  mime_type : String?,
) -> Unit {
  self.register_template_definition(
    @types.ResourceTemplateDefinition::new(
      uri_template,
      name,
      description?,
      mime_type?,
    ),
  )
}

///|
fn ResourceRegistry::register_template_definition(
  self : ResourceRegistry,
  definition : @types.ResourceTemplateDefinition,
) -> Unit {
  self.templates.set(definition.uri_template, definition)
}

///|
fn ResourceRegistry::list_resources(
  self : ResourceRegistry,
) -> Array[@resource.ResourceDefinition] {
  let entries : Array[ResourceEntry] = Array::from_iter(self.resources.values())
  entries.sort_by(fn(a, b) { a.definition.uri.compare(b.definition.uri) })
  entries.map(fn(entry) { entry.definition })
}

///|
fn ResourceRegistry::list_templates(
  self : ResourceRegistry,
) -> Array[@resource.ResourceTemplateDefinition] {
  let entries = Array::from_iter(self.templates.values())
  entries.sort_by(fn(a, b) { a.uri_template.compare(b.uri_template) })
  entries
}

///|
async fn ResourceRegistry::read_resource(
  self : ResourceRegistry,
  uri : String,
  context : @runtime.RequestContext,
  params : Json,
) -> Result[@resource.ResourceReadOutcome, @types.MCPError] {
  match self.resources.get(uri) {
    Some(entry) => {
      let handler = entry.handler
      handler(context, params)
    }
    // Per 2026-07-28 spec, resource-not-found is InvalidParams (-32602),
    // not the old -32002 or MethodNotFound.
    None => Err(@types.InvalidParams("Resource not found: " + uri))
  }
}