# SPDX-FileCopyrightText: 2017 Justin Schneck
# SPDX-FileCopyrightText: 2022 Frank Hunleth
#
# SPDX-License-Identifier: Apache-2.0
#
defmodule Nerves.Artifact.BuildRunners.Docker.Volume do
  @moduledoc false
  import Nerves.Artifact.BuildRunners.Docker.Utils
  alias Nerves.Artifact

  @spec name(Nerves.Package.t()) :: String.t()
  def name(pkg) do
    "#{pkg.app}-#{id(pkg)}"
  end

  @spec id(Nerves.Package.t()) :: String.t()
  def id(pkg) do
    id_file = id_file(pkg)

    if File.exists?(id_file) do
      File.read!(id_file)
    else
      create_id(pkg)
      id(pkg)
    end
  end

  defp id_file(pkg) do
    Artifact.build_path(pkg)
    |> Path.join(".docker_id")
  end

  defp create_id(pkg) do
    id_file = id_file(pkg)
    id = Nerves.Utils.random_alpha_num(16)

    Path.dirname(id_file)
    |> File.mkdir_p!()

    File.write!(id_file, id)
  end

  @spec delete(String.t()) :: :ok
  def delete(volume_name) do
    shell_info("Deleting build volume #{volume_name}")
    args = ["volume", "rm", volume_name]

    case Mix.Nerves.Utils.shell("docker", args) do
      {_result, 0} ->
        :ok

      {_result, _} ->
        Mix.raise("""
        Nerves Docker build_runner encountered an error while deleting volume #{volume_name}
        """)
    end
  end

  @spec exists?(String.t()) :: boolean()
  def exists?(volume_name) do
    cmd = "docker"
    args = ["volume", "ls", "-f", "name=#{volume_name}", "-q"]

    case Nerves.Port.cmd(cmd, args, stderr_to_stdout: true) do
      {<<^volume_name, _tail::binary>>, 0} ->
        true

      {<<"Cannot connect to the Docker daemon", _tail::binary>>, _} ->
        Mix.raise("Nerves Docker build_runner is unable to connect to docker daemon")

      _ ->
        false
    end
  end

  @spec create(String.t()) :: :noop
  def create(volume_name) do
    cmd = "docker"
    args = ["volume", "create", "--name", volume_name]

    case Nerves.Port.cmd(cmd, args) do
      {_, 0} -> :noop
      _ -> Mix.raise("Nerves Docker build_runner could not create docker volume #{volume_name}")
    end
  end
end
