# `Dala.Plugin.Lifecycle`
[🔗](https://github.com/manhvu/dala/blob/main/lib/dala/plugin/lifecycle.ex#L1)

Lifecycle management for Dala plugins.

Manages the state transitions of plugins through their lifecycle:

    :registered → :initialized → :active → :registered → :unloaded

Each transition validates prerequisites and updates the registry.

## Lifecycle States

- `:registered` — Plugin struct is in the registry, no resources allocated
- `:initialized` — `init/1` called successfully, resources allocated
- `:active` — Dependencies satisfied, plugin is ready for use
- `:error` — An error occurred during a transition
- `:unloaded` — `cleanup/1` called, plugin removed from active service

## Usage

    # Initialize a plugin (allocates resources)
    {:ok, state} = Dala.Plugin.Lifecycle.init(MyPlugin, opts: [])

    # Activate a plugin (checks dependencies, marks ready)
    :ok = Dala.Plugin.Lifecycle.activate(MyPlugin)

    # Check if a plugin supports a platform
    true = Dala.Plugin.Lifecycle.supports_platform?(MyPlugin, :ios)

    # Negotiate capabilities
    {:ok, [:gestures, :animation]} = Dala.Plugin.Lifecycle.negotiate_capabilities(MyPlugin, [:gestures, :animation, :textures])

    # Deactivate (marks as registered again)
    :ok = Dala.Plugin.Lifecycle.deactivate(MyPlugin)

    # Cleanup (releases resources)
    :ok = Dala.Plugin.Lifecycle.cleanup(MyPlugin)

# `status`

```elixir
@type status() :: :registered | :initialized | :active | :error | :unloaded
```

# `activate`

```elixir
@spec activate(module()) :: :ok | {:error, term()}
```

Activates a plugin, transitioning from `:initialized` → `:active`.

Checks that all declared dependencies are satisfied (registered and
version-compatible) before allowing activation.

Returns `:ok` on success or `{:error, reason}` on failure.

# `check_dependencies`

```elixir
@spec check_dependencies(module()) :: :ok | {:error, term()}
```

Validates that all declared dependencies are registered and version-compatible.

For each dependency `{plugin_name, version_req}`, checks that:
1. The dependency plugin is registered in the registry
2. The dependency plugin's `schema_version` satisfies the version requirement

Returns `:ok` if all dependencies are satisfied, or
`{:error, {:unsatisfied, [{name, reason}]}}` with details on failures.

# `cleanup`

```elixir
@spec cleanup(module()) :: :ok | {:error, term()}
```

Cleans up a plugin by calling its `cleanup/1` callback.

Transitions to `:unloaded` after cleanup. The plugin's runtime state
is cleared from the registry.

Returns `:ok` on success or `{:error, reason}` on failure.

# `deactivate`

```elixir
@spec deactivate(module()) :: :ok | {:error, term()}
```

Deactivates a plugin, transitioning from `:active` → `:registered`.

The plugin remains in the registry but is no longer considered active.
Its runtime state is preserved for potential re-activation.

Returns `:ok` on success or `{:error, reason}` on failure.

# `init`

```elixir
@spec init(
  module(),
  keyword()
) :: {:ok, term()} | {:error, term()}
```

Initializes a plugin by calling its `init/1` callback.

Transitions status from `:registered` → `:initialized` on success.
Transitions to `:error` on failure.

Returns `{:ok, state}` on success or `{:error, reason}` on failure.

# `negotiate_capabilities`

```elixir
@spec negotiate_capabilities(module(), [atom()]) ::
  {:ok, [atom()]} | {:error, {:missing, [atom()]}}
```

Negotiates capabilities between what a consumer requires and what a plugin provides.

Returns `{:ok, available}` where `available` is the intersection of
`required_caps` and the plugin's declared capabilities, or
`{:error, {:missing, missing_caps}}` if any required capabilities
are not provided by the plugin.

# `status`

```elixir
@spec status(module()) :: status() | :not_registered
```

Returns the current lifecycle status of a plugin.

Returns the status atom, or `:not_registered` if the plugin is not
in the registry.

# `supports_platform?`

```elixir
@spec supports_platform?(module(), Dala.Plugin.platform()) :: boolean()
```

Checks whether a plugin supports a given platform.

Returns `true` if the platform is in the plugin's `platforms` list,
`false` otherwise.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
