defmodule Raxol.Terminal.Buffer.SafeManager do @moduledoc """ Safe buffer manager that handles buffer operations with error recovery. This module provides a safe interface to buffer operations, ensuring that failures don't crash the system and providing fallback behavior. """ @doc """ Starts a safe manager process. """ @spec start_link() :: {:ok, pid()} | {:error, term()} def start_link do # For now, delegate to regular Manager GenServer.start_link(Raxol.Terminal.ScreenBuffer.Manager, %{}, name: __MODULE__) end @doc """ Safely writes data to the buffer. """ @spec write(pid() | atom(), binary()) :: :ok | {:error, term()} def write(manager, data) when is_binary(data) do GenServer.call(manager, {:write, data}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def write(_manager, _data), do: {:error, :invalid_data} @doc """ Safely reads from the buffer. """ @spec read(pid() | atom(), non_neg_integer()) :: {:ok, binary()} | {:error, term()} def read(manager, count) when is_integer(count) and count > 0 do GenServer.call(manager, {:read, count}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def read(_manager, _count), do: {:error, :invalid_count} @doc """ Safely resizes the buffer. """ @spec resize(pid() | atom(), non_neg_integer(), non_neg_integer()) :: :ok | {:error, term()} def resize(manager, width, height) when is_integer(width) and width > 0 and is_integer(height) and height > 0 do GenServer.call(manager, {:resize, width, height}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def resize(_manager, _width, _height), do: {:error, :invalid_dimensions} @doc """ Safely clears the buffer. """ @spec clear(pid() | atom()) :: :ok | {:error, term()} def clear(manager) do GenServer.call(manager, :clear) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end @doc """ Gets buffer info safely. """ @spec info(pid() | atom()) :: {:ok, map()} | {:error, term()} def info(manager) do GenServer.call(manager, :info) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end @doc """ Safely gets a cell from the buffer. """ @spec get_cell(pid() | atom(), non_neg_integer(), non_neg_integer()) :: {:ok, map()} | {:error, term()} def get_cell(manager, x, y) when is_integer(x) and x >= 0 and is_integer(y) and y >= 0 do GenServer.call(manager, {:get_cell, x, y}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def get_cell(_manager, _x, _y), do: {:error, :invalid_coordinates} @doc """ Safely sets a cell in the buffer. """ @spec set_cell(pid() | atom(), non_neg_integer(), non_neg_integer(), map()) :: :ok | {:error, term()} def set_cell(manager, x, y, cell) when is_integer(x) and x >= 0 and is_integer(y) and y >= 0 and is_map(cell) do GenServer.call(manager, {:set_cell, x, y, cell}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def set_cell(_manager, _x, _y, _cell), do: {:error, :invalid_arguments} @doc """ Safely scrolls the buffer. """ @spec scroll(pid() | atom(), integer()) :: :ok | {:error, term()} def scroll(manager, lines) when is_integer(lines) do GenServer.call(manager, {:scroll, lines}) rescue error -> {:error, error} catch :exit, reason -> {:error, {:exit, reason}} end def scroll(_manager, _lines), do: {:error, :invalid_lines} end