defmodule Cats do

  @base_dir "cats"

  def run() do
    process_type = :link # :monitor
    pid = start(process_type) |> IO.inspect
    IO.puts "time to send Thomas #{inspect pid}"
    send pid, {self, "Michigan", "Thomas"}
    pid = receive do
      {:EXIT, pid, reason} ->
        # this won't happen... we are linked! unless exit signals are trapped
        IO.puts "The process is down... I'm going down too ahhhhh..... Reason: #{inspect reason}"
        start(process_type)
      {:DOWN, ref, :process, pid, reason} ->
        IO.puts "the process is down... I should restart it.  Reason: #{inspect reason}"
        start(process_type)
      resp ->
        IO.puts "Michigan/Thomas: #{inspect resp}"
        pid
    after 5000 ->
      IO.puts "Timed out waiting for Michigan/Thomas"
    end
    IO.puts "time to send Felix #{inspect pid}"
    send pid, {self, "Virginia", "Felix"}
    pid = receive do
      {:EXIT, pid, reason} ->
        # this won't happen... we are linked! unless exit signals are trapped
        IO.puts "The process is down... I'm going down too ahhhhh..... Reason: #{inspect reason}"
        start(process_type)
      {:DOWN, ref, :process, pid, reason} ->
        IO.puts "the process is down... I should restart it. Reason: #{inspect reason}"
        start(process_type)
      resp ->
        IO.puts "Virginia/Felix: #{inspect resp}"
        pid
    after 5000 ->
      IO.puts "Timed out waiting for Virginia/Felix"
    end
  end

  def start(nil) do
    spawn &cat_message/0
  end
  def start(:link) do
    Process.flag(:trap_exit, true)
    spawn_link &cat_message/0
  end
  def start(:monitor) do
    {pid, ref} = spawn_monitor &cat_message/0
    pid
  end

  def cat_message() do
    receive do
      {from, state, cat} ->
        send from, find_cat(state, cat)
        cat_message
      :quit -> :ok
    end
  end

  def find_cat(state, cat) do
    [@base_dir, String.downcase(state), String.downcase(cat) <> ".cat"]
    |> Path.join()
    |> File.read!()
  end

end