defmodule Raxol.Terminal.Buffer.Scrollback do
  @moduledoc """
  Handles scrollback buffer operations for the screen buffer.
  This module manages the history of lines that have scrolled off the screen,
  including adding, retrieving, and clearing scrollback content.
  """

  # ScreenBuffer and Cell aliases removed - not currently used

  @doc """
  Adds a line to the scrollback buffer.
  """
  def add_line(buffer, line) when is_list(line) do
    scrollback = [line | buffer.scrollback]
    scrollback = trim_scrollback(scrollback, buffer.scrollback_limit)
    %{buffer | scrollback: scrollback}
  end

  def add_line(buffer, _), do: buffer

  @doc """
  Adds multiple lines to the scrollback buffer.
  """
  def add_lines(buffer, lines) when is_list(lines) do
    scrollback = lines ++ buffer.scrollback
    scrollback = trim_scrollback(scrollback, buffer.scrollback_limit)
    %{buffer | scrollback: scrollback}
  end

  def add_lines(buffer, _), do: buffer

  @doc """
  Gets a specific line from the scrollback buffer.
  """
  def get_line(buffer, index) when index >= 0 do
    buffer.scrollback
    |> Enum.reverse()
    |> Enum.at(index)
  end

  def get_line(_, _), do: nil

  @doc """
  Gets lines from the scrollback buffer.
  """
  def get_lines(buffer, start, count) when start >= 0 and count > 0 do
    buffer.scrollback
    |> Enum.reverse()
    |> Enum.slice(start, count)
  end

  def get_lines(_, _, _), do: []

  @doc """
  Gets the total number of lines in the scrollback buffer.
  """
  def size(buffer) do
    length(buffer.scrollback)
  end

  @doc """
  Clears the scrollback buffer.
  """
  def clear(buffer) do
    %{buffer | scrollback: []}
  end

  @doc """
  Sets the scrollback limit.
  """
  def set_limit(buffer, limit) when limit >= 0 do
    scrollback = trim_scrollback(buffer.scrollback, limit)
    %{buffer | scrollback: scrollback, scrollback_limit: limit}
  end

  def set_limit(buffer, _), do: buffer

  @doc """
  Gets the current scrollback limit.
  """
  def get_limit(buffer) do
    buffer.scrollback_limit
  end

  @doc """
  Checks if the scrollback buffer is full.
  """
  def full?(buffer) do
    length(buffer.scrollback) >= buffer.scrollback_limit
  end

  @doc """
  Gets the oldest line in the scrollback buffer.
  """
  def get_oldest_line(buffer) do
    List.last(buffer.scrollback)
  end

  @doc """
  Gets the newest line in the scrollback buffer.
  """
  def get_newest_line(buffer) do
    List.first(buffer.scrollback)
  end

  # Private helper functions

  defp trim_scrollback(scrollback, limit) do
    case length(scrollback) > limit do
      true ->
        scrollback
        |> Enum.take(limit)

      false ->
        scrollback
    end
  end

  defstruct lines: [], limit: Raxol.Core.Defaults.scrollback_limit()

  @type t :: %__MODULE__{
          lines: list(),
          limit: integer()
        }

  @doc """
  Returns a new scrollback buffer with default settings.
  """
  def new do
    %__MODULE__{}
  end

  @doc """
  Gets the memory usage of the scrollback buffer.
  """
  def get_memory_usage(%__MODULE__{} = scrollback) do
    # Estimate memory usage based on number of lines and average line length
    total_cells =
      Enum.reduce(scrollback.lines, 0, fn line, acc ->
        acc + length(line)
      end)

    # Rough estimate: each cell is about 64 bytes (including overhead)
    total_cells * 64
  end

  @doc """
  Cleans up the scrollback buffer.
  """
  def cleanup(%__MODULE__{} = scrollback) do
    %{scrollback | lines: []}
  end
end
