 defmodule Baumeister.Observer do
+  @moduledoc """
+  Defines the API, which a specific observer has to implement.
+  """
   alias Baumeister.EventCenter
   alias Baumeister.BaumeisterFile
   alias Baumeister.Observer
-  @moduledoc """
-  Defines the API, which a specific observer has to implement.
+
+  @typedoc """
+  A mapping between plugin name and its current state.
   """
+  @type plugin_state :: %{atom => any}
+
+  @typedoc """
+  Allowed return values for an Observer Plugin:
+  * `:ok` if everything went fine. We return the URL and BaumeisterFile.
+  * `:error` somethings fails. Stops the Observer with a crash
+  * `:stop` The Plugin decides, that the Observer should stop.
+  """
+  @type observer_return_t ::
+    {:ok, String.t, String.t, any} |
+    {:ok, any} |
+    {:error, any, any} |
+    {:stop, any}
+
 
   @doc """
   Initializes the observer. It is called with the observer's

  the URL of the target repository and the content of the `BaumeisterFile`,
  which is used to determine the nodes to execute the build.
  """
  @callback observe(state :: any) :: {:ok, String.t, String.t} | :error

  ###################################################
  ##

  ###################################################

  use GenServer
  require Logger

  defstruct state: %{}, observer_pid: nil,
    observer_fun: nil, init_fun: nil, name: "anonymous observer"

  @doc """
  Convenience function to start the observer and configure
  it with the singleton plugin `mod`.
  """
  def start_link(mod, configuration) when is_atom(mod) do
    {:ok, pid} = start_link(Atom.to_string(mod))
    :ok = configure(pid, mod, configuration)
    {:ok, pid}
  end
  @doc """
  Starts the oberver process
  """
  def start_link(name \\ "anonymous observer")  do
    GenServer.start_link(__MODULE__, [name])
  end

  @doc """
  Configures the Observer with a list of plugin names and their
  initializations. This list is executed in reverse order.
  """
  def configure(observer, mod, config) do
    configure(observer, [{mod, config}])
  end
  def configure(observer, {mod, config}) do
    configure(observer, [{mod, config}])
  end
  def configure(observer, plug_list) when is_list(plug_list) do
    GenServer.call(observer, {:configure, plug_list})
  end

  @doc """
