add getByIds

add getByIds

defmodule Exsoda.Reader do
  alias Exsoda.{Soql, Http}
  alias HTTPoison.{AsyncResponse, AsyncStatus, AsyncHeaders, AsyncChunk, AsyncEnd}
  alias NimbleCSV.RFC4180, as: CSV
  require Logger

  defmodule Query do
    defstruct fourfour: nil,
      opts: [],
      query: %{}
  end

  def query(fourfour, options \\ []) do
    %Query{
      fourfour: fourfour,
      opts: Http.options(options),
      query: %{}
    }
  end

  defp view_columns(decoded) do
    columns = decoded
    |> Map.get("columns", [])
    |> Enum.map(fn column -> {column["name"], column["dataTypeName"]} end)
    |> Enum.into(%{})

    {:ok, columns}
  end

  def get_views(fourfours, options \\ []) do
    state = query(nil, options)

    fourfours = fourfours
    |> Enum.map(fn ff -> "ids=#{Http.encode(ff)}" end)
    |> Enum.join("&")
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views?method=getByIds&#{fourfours}.json"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def get_view(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def get_unpublished_copy(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json?method=getPublicationGroup&stage=unpublished"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def get_published_copy(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json?method=getPublicationGroup&stage=published"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def replication(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}/replication.json"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def geocoding(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/geocoding/#{Http.encode(fourfour)}?method=pending"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  defp get_columns(query) do
    with {:ok, view} <- get_view(query) do
      view_columns(view)
    end
  end

  def run(%Query{} = state) do
    with {:ok, columns} <- get_columns(state),
         {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do

      query = URI.encode_query(state.query)

      stream = "#{base}/id/#{Http.encode(state.fourfour)}.csv?#{query}"
      |> HTTPoison.get(Http.headers(state), [{:stream_to, self()} | options])
      |> as_line_stream
      |> CSV.parse_stream(headers: false)
      |> Stream.transform(nil,
        fn
          header, nil ->
            {[], header}
          row, header ->
            converted_row = Enum.zip(header, row)
            |> Enum.map(fn {column_name, datum} ->
              type = Map.get(columns, column_name)
              {column_name, Soql.from_string(type, datum)}
            end)

            {[converted_row], header}
        end
      )

      {:ok, stream}
    end
  end

  defp as_line_stream({:ok, %AsyncResponse{id: ref}}) do
    Stream.resource(
      fn -> :ok end,
      fn state ->
        receive do
          %AsyncStatus{id: ^ref, code: _}     -> {[], state}
          %AsyncHeaders{id: ^ref, headers: _} -> {[], state}
          %AsyncEnd{id: ^ref}                 -> {:halt, state}
          %AsyncChunk{id: ^ref, chunk: c}     ->
            lines = c
            |> String.split("\n")
            |> Enum.reject(fn
              "" -> true
              _ -> false
            end)
            {lines, state}
        end
      end,
      fn _state -> :ok end
    )
  end

  defp as_line_stream(failure), do: failure

  @operations [:where, :limit, :offset, :group, :q]

  defp put_q(%Query{} = state, name, value) do
    query = Map.put(state.query, name, value)
    struct(state, query: query)
  end

  def order(state, expr , :asc) do
    order(state, expr <> " ASC")
  end
  def order(state, expr , :desc) do
    order(state, expr <> " DESC")
  end
  def order(state, expr) do
    put_q(state, "$order", expr)
  end

  Enum.each(@operations, fn param ->
    def unquote(param)(state, expr) do
      put_q(state, "$" <> Atom.to_string(unquote(param)), expr)
    end
  end)

  def select(state, columns) do
    put_q(state, "$select", Enum.join(columns, ", "))
  end
end

defmodule Exsoda.Reader do
  alias Exsoda.{Soql, Http}
  alias HTTPoison.{AsyncResponse, AsyncStatus, AsyncHeaders, AsyncChunk, AsyncEnd}
  alias NimbleCSV.RFC4180, as: CSV
  require Logger

  defmodule Query do
    defstruct fourfour: nil,
      opts: [],
      query: %{}
  end

  def query(fourfour, options \\ []) do
    %Query{
      fourfour: fourfour,
      opts: Http.options(options),
      query: %{}
    }
  end

  defp view_columns(decoded) do
    columns = decoded
    |> Map.get("columns", [])
    |> Enum.map(fn column -> {column["name"], column["dataTypeName"]} end)
    |> Enum.into(%{})

    {:ok, columns}
  end

  def get_view(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def get_unpublished_copy(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json?method=getPublicationGroup&stage=unpublished"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def get_published_copy(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}.json?method=getPublicationGroup&stage=published"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def replication(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/views/#{Http.encode(fourfour)}/replication.json"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  def geocoding(%Query{fourfour: fourfour} = state) do
    with {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do
      "#{base}/geocoding/#{Http.encode(fourfour)}?method=pending"
      |> HTTPoison.get(Http.headers(state), options)
      |> Http.as_json
    end
  end

  defp get_columns(query) do
    with {:ok, view} <- get_view(query) do
      view_columns(view)
    end
  end

  def run(%Query{} = state) do
    with {:ok, columns} <- get_columns(state),
         {:ok, base} <- Http.base_url(state),
         {:ok, options} <- Http.http_opts(state) do

      query = URI.encode_query(state.query)

      stream = "#{base}/id/#{Http.encode(state.fourfour)}.csv?#{query}"
      |> HTTPoison.get(Http.headers(state), [{:stream_to, self()} | options])
      |> as_line_stream
      |> CSV.parse_stream(headers: false)
      |> Stream.transform(nil,
        fn
          header, nil ->
            {[], header}
          row, header ->
            converted_row = Enum.zip(header, row)
            |> Enum.map(fn {column_name, datum} ->
              type = Map.get(columns, column_name)
              {column_name, Soql.from_string(type, datum)}
            end)

            {[converted_row], header}
        end
      )

      {:ok, stream}
    end
  end

  defp as_line_stream({:ok, %AsyncResponse{id: ref}}) do
    Stream.resource(
      fn -> :ok end,
      fn state ->
        receive do
          %AsyncStatus{id: ^ref, code: _}     -> {[], state}
          %AsyncHeaders{id: ^ref, headers: _} -> {[], state}
          %AsyncEnd{id: ^ref}                 -> {:halt, state}
          %AsyncChunk{id: ^ref, chunk: c}     ->
            lines = c
            |> String.split("\n")
            |> Enum.reject(fn
              "" -> true
              _ -> false
            end)
            {lines, state}
        end
      end,
      fn _state -> :ok end
    )
  end

  defp as_line_stream(failure), do: failure

  @operations [:where, :limit, :offset, :group, :q]

  defp put_q(%Query{} = state, name, value) do
    query = Map.put(state.query, name, value)
    struct(state, query: query)
  end

  def order(state, expr , :asc) do
    order(state, expr <> " ASC")
  end
  def order(state, expr , :desc) do
    order(state, expr <> " DESC")
  end
  def order(state, expr) do
    put_q(state, "$order", expr)
  end

  Enum.each(@operations, fn param ->
    def unquote(param)(state, expr) do
      put_q(state, "$" <> Atom.to_string(unquote(param)), expr)
    end
  end)

  def select(state, columns) do
    put_q(state, "$select", Enum.join(columns, ", "))
  end
end


WIP Asteroid process

WIP Asteroid process

defmodule Game.Asteroid do

   @moduledoc """
   Asteroid process.
   """

   use GenServer

   def start_link do
     a = %{:pos => %World.Point{},
           :velocity => %World.Velocity{},
           :radius => 10.0}
     GenServer.start_link(__MODULE__, a, [])
   end

   def init(a) do
     {:ok, a}
   end

   def move(asteroid, delta_t_ms) do
     GenServer.cast(asteroid, {:move, delta_t_ms})
   end

   def handle_cast({:move, delta_t_ms}, asteroid) do
     {:noreply, asteroid}
   end

   # {:ok, a} = Game.Asteroid.start_link
   # Game.Asteroid.move(a,1)

end

defmodule Game.Asteroid do

   @moduledoc """
   Asteroid process.
   """

   use GenServer

   def start_link do
     GenServer.start_link(__MODULE__, :ok, [])
   end

   def init(:ok) do
     {:ok, %{}}
   end

   def handle_cast({:move, delta_t_ms}, asteroid) do
     {:noreply, asteroid}
   end

end


ENH cleanup docs for tempfs

ENH cleanup docs for tempfs

defmodule Radpath.Tempfs do
   defmacro __using__([]) do
     quote do

     @doc """

     To create a temp file and write to it without arguments:

         Radpath.mktempfile |> File.write("test123")

     """
     def mktempfile() do
       Tempfile.get_name
     end

     @doc """
     To create a temp file with arguments (ext and path) and write to it. Default value for extension is '.tmp':

         Radpath.mktempfile(".log", "/home/lowks/Downloads") |> File.write("abcdef")

     """

     def mktempfile(ext, path) when is_bitstring(path) and is_bitstring(ext) do
        Tempfile.get_name("", [ext: ext, path: path])
     end

    @doc """
    To create a temp file at a certain location without extension and write to it:

        Radpath.mktempfile("/home/lowks/Downloads") |> File.write("abcdef")

    """
    def mktempfile(path) when is_bitstring(path) do
      Tempfile.get_name("", [ext: ".tmp", path: path])
    end

    @doc """
    To create a temp dir without arguments:

        Radpath.mktempdir

    """
    def mktempdir do
      Tempfile.get_name |> Path.rootname |> do_mkdir
    end

    @doc """
    To create a temp dir at a specific location:

        Radpath.mktempdir("/home/lowks/Downloads")

    """
    def mktempdir(path) when is_bitstring(path) do
      Tempfile.get_name([path: make_into_path(path)]) |> Path.rootname |> do_mkdir
    end

  end
  end
end

defmodule Radpath.Tempfs do
   defmacro __using__([]) do
     quote do

     @doc """

     To create a temp file without arguments:

         Radpath.mktempfile

     """
     def mktempfile() do
       Tempfile.open
     end

     @doc """
     To create a temp file with arguments. Default value for extension is '.tmp':

         Radpath.mktempfile(".log", "/home/lowks/Downloads") |> File.write("abcdef")

     """

     def mktempfile(ext, path) when is_bitstring(path) and is_bitstring(ext) do
        Tempfile.get_name("", [ext: ext, path: path])
     end

    @doc """
    To create a temp file at a certain location:

        Radpath.mktempfile("/home/lowks/Downloads") |> File.write("abcdef")

    """
    def mktempfile(path) when is_bitstring(path) do
      Tempfile.get_name("", [ext: ".tmp", path: path])
    end

    @doc """
    To create a temp dir without arguments:

        Radpath.mktempdir

    """
    def mktempdir do
      Tempfile.get_name |> Path.rootname |> do_mkdir
    end

    @doc """
    To create a temp dir with arguments:

        Radpath.mktempdir("/home/lowks/Downloads")

    """
    def mktempdir(path) when is_bitstring(path) do
      Tempfile.get_name([path: make_into_path(path)]) |> Path.rootname |> do_mkdir
    end

  end
  end
end


again

again

defmodule Tcp do
	use Supervisor
	def atom_join(x, y) do
		a=to_string(x) <> "." <> to_string(y)
		String.to_atom(a)
	end
	def start_link(id, func1, func2) do
		import Supervisor.Spec, warn: false
		children = [
			worker(__MODULE__, [func1, id, "/", {0,0,0,0}], function: :run),
			worker(__MODULE__, [func2, :tcp_internal, "/priv/", {127,0,0,1}], function: :run, id: :tcp_internal),
		]
		opts = [strategy: :one_for_one, name: Tcp.Supervisor]
		Supervisor.start_link(children, opts)
	end
	def run(func, id, r, ip) do
		routes = [ {r, Tcp.Handler, [func, ip]}	]
		dispatch = :cowboy_router.compile([{:_, routes}])
		p = Port.port
		if id == :tcp_internal do p = p+1000 end
		opts = [port: p, ip: ip]
		env = [env: [dispatch: dispatch]]
		{:ok, _pid} = :cowboy.start_http(atom_join(:http, id), 100, opts, env)
	end
	def get_local(ip, port, x) do get(ip, port, x, '/priv') end
	def get(ip, port, a, y \\ '') do
		url = 'http://' ++ to_char_list(ip) ++ ':' ++ to_char_list(to_string(port)) ++ y
		content_type = 'application/octet-stream'
		request = {url, [], content_type, PackWrap.pack(a)}
		#:httpc.request(:post, request, [{:timeout, 2000}], [])#hopefully 2 seconds?
		x = :httpc.request(:post, request, [], [])
		case x do
			{:ok, z} ->
				b = z |> elem(2)
				if b == [] do [] else PackWrap.unpack(b) end
			{:error, :socket_closed_remotely} -> get(ip, port, a, y)
			{:error, {:failed_connect, _}} -> nil
			x ->
				IO.puts("TCP WEIRD #{inspect x}")
				x
		end
	end
end
defmodule Tcp.Handler do
	def init({:tcp, :http}, req, opts) do
		#x = :cowboy_req.part(req)
		#IO.puts("cowboy req #{inspect x}")
		#{:ok, headers, req2} = :cowboy_req.part(req)
		#{:ok, data, req3} = :cowboy_req.part_body(req2)
		#{:file, "inputfile", filename, contentType, _} = :cow_multipart.form_data(headers)
		#{:ok, req3, opts}
		{:ok, req, opts}
	end
	def body(req, opts) do
		[func, ip] = opts
		{status, data, req2} = :cowboy_req.body(req, opts)
		IO.puts("body #{inspect data}")
		cond do
			status == :ok -> data
			true ->
				:timer.sleep(50)
				body(req, opts)
		end
	end
	def handle(req, opts) do
		[func, ip] = opts
		f = fn(x) -> tl(x) end
		if ip == {127,0,0,1} do
			f = fn(x) -> tl(tl(tl(tl(tl(tl(x)))))) end
		end
		headers = [{"content-type", "application/octet-stream"},
							 {"access-control-allow-origin", "*"}]
		#IO.puts("tcp rec #{inspect req}")
		#length = req |> elem(16) |> tl |> hd |> elem(1) |> String.to_integer
		#IO.puts("length #{inspect length}")
		#body_length = req |> elem(21) |> byte_size
		#IO.puts("body length #{inspect body_length}")
		#if body_length < length do
		b = body(req, opts) |> PackWrap.unpack
		IO.puts("before func #{inspect b}")
		b = b |> func.() |> PackWrap.pack
		IO.puts("response #{inspect b}")
		{:ok, resp} = :cowboy_req.reply(200, headers, b, req)

			#handle(req, opts)
			#IO.puts("broke")
			#io:format("Received file ~p of content-type ~p as follow:~n~p~n~n",
			#					[Filename, ContentType, Data]),
			#{:ok, req3, opts}
			#{:ok, req, opts}#why is func there???
		{:ok, resp, opts}
	#else
	#		body = req |> elem(21) |> PackWrap.unpack |> func.() |> PackWrap.pack
	#		{:ok, resp} = :cowboy_req.reply(200, headers, body, req)
	#		{:ok, resp, opts}#why is func there???
	#	end
	end
	def terminate(_reason, _req, _state) do
		:ok
	end
end

defmodule Tcp do
	use Supervisor
	def atom_join(x, y) do
		a=to_string(x) <> "." <> to_string(y)
		String.to_atom(a)
	end
	def start_link(id, func1, func2) do
		import Supervisor.Spec, warn: false
		children = [
			worker(__MODULE__, [func1, id, "/", {0,0,0,0}], function: :run),
			worker(__MODULE__, [func2, :tcp_internal, "/priv/", {127,0,0,1}], function: :run, id: :tcp_internal),
		]
		opts = [strategy: :one_for_one, name: Tcp.Supervisor]
		Supervisor.start_link(children, opts)
	end
	def run(func, id, r, ip) do
		routes = [ {r, Tcp.Handler, [func, ip]}	]
		dispatch = :cowboy_router.compile([{:_, routes}])
		p = Port.port
		if id == :tcp_internal do p = p+1000 end
		opts = [port: p, ip: ip]
		env = [env: [dispatch: dispatch]]
		{:ok, _pid} = :cowboy.start_http(atom_join(:http, id), 100, opts, env)
	end
	def get_local(ip, port, x) do get(ip, port, x, '/priv') end
	def get(ip, port, a, y \\ '') do
		url = 'http://' ++ to_char_list(ip) ++ ':' ++ to_char_list(to_string(port)) ++ y
		content_type = 'application/octet-stream'
		request = {url, [], content_type, PackWrap.pack(a)}
		#:httpc.request(:post, request, [{:timeout, 2000}], [])#hopefully 2 seconds?
		x = :httpc.request(:post, request, [], [])
		case x do
			{:ok, z} ->
				b = z |> elem(2)
				if b == [] do [] else PackWrap.unpack(b) end
			{:error, :socket_closed_remotely} -> get(ip, port, a, y)
			{:error, {:failed_connect, _}} -> nil
			x ->
				IO.puts("TCP WEIRD #{inspect x}")
				x
		end
	end
end
defmodule Tcp.Handler do
	def init({:tcp, :http}, req, opts) do
		#x = :cowboy_req.part(req)
		#IO.puts("cowboy req #{inspect x}")
		#{:ok, headers, req2} = :cowboy_req.part(req)
		#{:ok, data, req3} = :cowboy_req.part_body(req2)
		#{:file, "inputfile", filename, contentType, _} = :cow_multipart.form_data(headers)
		#{:ok, req3, opts}
		{:ok, req, opts}
	end
	def body(req, opts) do
		[func, ip] = opts
		{status, data, req2} = :cowboy_req.body(req, opts)
		IO.puts("body #{inspect data}")
		cond do
			status == :ok -> data
			true ->
				:timer.sleep(50)
				body(req, opts)
		end
	end
	def handle(req, opts) do
		[func, ip] = opts
		f = fn(x) -> tl(x) end
		if ip == {127,0,0,1} do
			f = fn(x) -> tl(tl(tl(tl(tl(tl(x)))))) end
		end
		headers = [{"content-type", "application/octet-stream"},
							 {"access-control-allow-origin", "*"}]
		IO.puts("tcp rec #{inspect req}")
		length = req |> elem(16) |> tl |> hd |> elem(1) |> String.to_integer
		IO.puts("length #{inspect length}")
		body_length = req |> elem(21) |> byte_size
		IO.puts("body length #{inspect body_length}")
		#if body_length < length do
		b = body(req, opts) |> PackWrap.unpack |> func.() |> PackWrap.pack
		{:ok, resp} = :cowboy_req.reply(200, headers, b, req)

			#handle(req, opts)
			#IO.puts("broke")
			#io:format("Received file ~p of content-type ~p as follow:~n~p~n~n",
			#					[Filename, ContentType, Data]),
			#{:ok, req3, opts}
			#{:ok, req, opts}#why is func there???
		{:ok, resp, opts}
	#else
	#		body = req |> elem(21) |> PackWrap.unpack |> func.() |> PackWrap.pack
	#		{:ok, resp} = :cowboy_req.reply(200, headers, body, req)
	#		{:ok, resp, opts}#why is func there???
	#	end
	end
	def terminate(_reason, _req, _state) do
		:ok
	end
end


trying to get multipart cowboy

trying to get multipart cowboy

defmodule Tcp do
	use Supervisor
	def atom_join(x, y) do
		a=to_string(x) <> "." <> to_string(y)
		String.to_atom(a)
	end
	def start_link(id, func1, func2) do
		import Supervisor.Spec, warn: false
		children = [
			worker(__MODULE__, [func1, id, "/", {0,0,0,0}], function: :run),
			worker(__MODULE__, [func2, :tcp_internal, "/priv/", {127,0,0,1}], function: :run, id: :tcp_internal),
		]
		opts = [strategy: :one_for_one, name: Tcp.Supervisor]
		Supervisor.start_link(children, opts)
	end
	def run(func, id, r, ip) do
		routes = [ {r, Tcp.Handler, [func, ip]}	]
		dispatch = :cowboy_router.compile([{:_, routes}])
		p = Port.port
		if id == :tcp_internal do p = p+1000 end
		opts = [port: p, ip: ip]
		env = [env: [dispatch: dispatch]]
		{:ok, _pid} = :cowboy.start_http(atom_join(:http, id), 100, opts, env)
	end
	def get_local(ip, port, x) do get(ip, port, x, '/priv') end
	def get(ip, port, a, y \\ '') do
		url = 'http://' ++ to_char_list(ip) ++ ':' ++ to_char_list(to_string(port)) ++ y
		content_type = 'application/octet-stream'
		request = {url, [], content_type, PackWrap.pack(a)}
		#:httpc.request(:post, request, [{:timeout, 2000}], [])#hopefully 2 seconds?
		x = :httpc.request(:post, request, [], [])
		case x do
			{:ok, z} ->
				b = z |> elem(2)
				if b == [] do [] else PackWrap.unpack(b) end
			{:error, :socket_closed_remotely} -> get(ip, port, a, y)
			{:error, {:failed_connect, _}} -> nil
			x ->
				IO.puts("TCP WEIRD #{inspect x}")
				x
		end
	end
end
defmodule Tcp.Handler do
	def init({:tcp, :http}, req, opts) do
		{:ok, req, opts}
	end
	def handle(req, opts) do
		[func, ip] = opts
		f = fn(x) -> tl(x) end
		if ip == {127,0,0,1} do
			f = fn(x) -> tl(tl(tl(tl(tl(tl(x)))))) end
		end
		headers = [{"content-type", "text/plain"},
							 {"access-control-allow-origin", "*"}]
		IO.puts("tcp rec #{inspect req}")
		length = req |> elem(16) |> tl |> hd |> elem(1) |> String.to_integer
		IO.puts("length #{inspect length}")
		body_length = req |> elem(21) |> byte_size
		IO.puts("body length #{inspect body_length}")
		if body_length < length do
			x = :cowboy_req.part(req)
			IO.puts("cowboy req #{inspect x}")
			{:ok, headers, req2} = :cowboy_req.part(req)
			{:ok, data, req3} = :cowboy_req.part_body(req2)
			{:file, "inputfile", filename, contentType, _} = :cow_multipart.form_data(headers)
			IO.puts("junk #{inspect filename} #{inspect contentType}")
			#io:format("Received file ~p of content-type ~p as follow:~n~p~n~n",
			#					[Filename, ContentType, Data]),
			{:ok, req3, opts}
			#{:ok, req, opts}#why is func there???
		else
			body = req |> elem(21) |> PackWrap.unpack |> func.() |> PackWrap.pack
			{:ok, resp} = :cowboy_req.reply(200, headers, body, req)
			{:ok, resp, opts}#why is func there???
		end
	end
	def terminate(_reason, _req, _state) do
		:ok
	end
end

defmodule Tcp do
	use Supervisor
	def atom_join(x, y) do
		a=to_string(x) <> "." <> to_string(y)
		String.to_atom(a)
	end
	def start_link(id, func1, func2) do
		import Supervisor.Spec, warn: false
		children = [
			worker(__MODULE__, [func1, id, "/", {0,0,0,0}], function: :run),
			worker(__MODULE__, [func2, :tcp_internal, "/priv/", {127,0,0,1}], function: :run, id: :tcp_internal),
		]
		opts = [strategy: :one_for_one, name: Tcp.Supervisor]
		Supervisor.start_link(children, opts)
	end
	def run(func, id, r, ip) do
		routes = [ {r, Tcp.Handler, [func, ip]}	]
		dispatch = :cowboy_router.compile([{:_, routes}])
		p = Port.port
		if id == :tcp_internal do p = p+1000 end
		opts = [port: p, ip: ip]
		env = [env: [dispatch: dispatch]]
		{:ok, _pid} = :cowboy.start_http(atom_join(:http, id), 100, opts, env)
	end
	def get_local(ip, port, x) do get(ip, port, x, '/priv') end
	def get(ip, port, a, y \\ '') do
		url = 'http://' ++ to_char_list(ip) ++ ':' ++ to_char_list(to_string(port)) ++ y
		content_type = 'application/octet-stream'
		request = {url, [], content_type, PackWrap.pack(a)}
		#:httpc.request(:post, request, [{:timeout, 2000}], [])#hopefully 2 seconds?
		x = :httpc.request(:post, request, [], [])
		case x do
			{:ok, z} ->
				b = z |> elem(2)
				if b == [] do [] else PackWrap.unpack(b) end
			{:error, :socket_closed_remotely} -> get(ip, port, a, y)
			{:error, {:failed_connect, _}} -> nil
			x ->
				IO.puts("TCP WEIRD #{inspect x}")
				x
		end
	end
end
defmodule Tcp.Handler do
	def init({:tcp, :http}, req, opts) do
		{:ok, req, opts}
	end
	def handle(req, opts) do
		[func, ip] = opts
		f = fn(x) -> tl(x) end
		if ip == {127,0,0,1} do
			f = fn(x) -> tl(tl(tl(tl(tl(tl(x)))))) end
		end
		headers = [{"content-type", "text/plain"},
							 {"access-control-allow-origin", "*"}]
		IO.puts("tcp rec #{inspect req}")
		length = req |> elem(16) |> tl |> hd |> elem(1) |> String.to_integer
		IO.puts("length #{inspect length}")
		body_length = req |> elem(21) |> byte_size
		IO.puts("body length #{inspect body_length}")
		if body_length < length do
			{:ok, headers, req2} = :cowboy_req.part(req)
			{:ok, data, req3} = :cowboy_req.part_body(req2)
			{:file, "inputfile", filename, contentType, _} = :cow_multipart.form_data(headers)
			IO.puts("junk #{inspect filename} #{inspect contentType}")
			#io:format("Received file ~p of content-type ~p as follow:~n~p~n~n",
			#					[Filename, ContentType, Data]),
			{:ok, req3, opts}
			#{:ok, req, opts}#why is func there???
		else
			body = req |> elem(21) |> PackWrap.unpack |> func.() |> PackWrap.pack
			{:ok, resp} = :cowboy_req.reply(200, headers, body, req)
			{:ok, resp, opts}#why is func there???
		end
	end
	def terminate(_reason, _req, _state) do
		:ok
	end
end


Fix not to ignore RT

Fix not to ignore RT

defmodule Mytwitter.Timeline do
  use GenServer
  require Logger

  def start_link do
    GenServer.start_link(__MODULE__, name: __MODULE__)
  end

  def init(_opts) do
    stream = ExTwitter.stream_user
    pid = self()
    spawn_link fn ->
      for message <- stream do
        send pid, message
      end
      exit :kill
    end
    {:ok, :ok}
  end

  def handle_info(message, :ok) do
    with tweet = %ExTwitter.Model.Tweet{} <- message,
    false <- tweet.user.protected,
    nil <- tweet.in_reply_to_screen_name,
    nil <- tweet.in_reply_to_status_id,
    nil <- tweet.in_reply_to_status_id_str,
    nil <- tweet.in_reply_to_user_id,
    nil <- tweet.in_reply_to_user_id_str,
    nil <- tweet.quoted_status,
    [] <- Map.get(tweet.entities, :hashtags, []),
    [] <- Map.get(tweet.entities, :media, []),
    [] <- Map.get(tweet.entities, :symbols, []),
    [] <- Map.get(tweet.entities, :urls, []) do
      Mytwitter.Web.Endpoint.broadcast!("timeline", "tweet", tweet)
    else
      _ ->
        Logger.debug(inspect message)
    end
    {:noreply, :ok}
  end
end

defmodule Mytwitter.Timeline do
  use GenServer
  require Logger

  def start_link do
    GenServer.start_link(__MODULE__, name: __MODULE__)
  end

  def init(_opts) do
    stream = ExTwitter.stream_user
    pid = self()
    spawn_link fn ->
      for message <- stream do
        send pid, message
      end
      exit :kill
    end
    {:ok, :ok}
  end

  def handle_info(message, :ok) do
    with tweet = %ExTwitter.Model.Tweet{} <- message,
    false <- tweet.user.protected,
    nil <- tweet.in_reply_to_screen_name,
    nil <- tweet.in_reply_to_status_id,
    nil <- tweet.in_reply_to_status_id_str,
    nil <- tweet.in_reply_to_user_id,
    nil <- tweet.in_reply_to_user_id_str,
    nil <- tweet.quoted_status,
    [] <- Map.get(tweet.entities, :hashtags, []),
    [] <- Map.get(tweet.entities, :media, []),
    [] <- Map.get(tweet.entities, :symbols, []),
    [] <- Map.get(tweet.entities, :urls, []),
    [] <- Map.get(tweet.entities, :user_mentions, []) do
      Mytwitter.Web.Endpoint.broadcast!("timeline", "tweet", tweet)
    else
      _ ->
        Logger.debug(inspect message)
    end
    {:noreply, :ok}
  end
end


Document better examples of action/2 overrides. Closes #1149

defmodule Phoenix.Controller do
  import Plug.Conn
  alias Plug.Conn.AlreadySentError

  require Logger

  @unsent [:unset, :set]

  @moduledoc """
  Controllers are used to group common functionality in the same
  (pluggable) module.

  For example, the route:

      get "/users/:id", MyApp.UserController, :show

  will invoke the `show/2` action in the `MyApp.UserController`:

      defmodule MyApp.UserController do
        use MyApp.Web, :controller

        def show(conn, %{"id" => id}) do
          user = Repo.get(User, id)
          render conn, "show.html", user: user
        end
      end

  An action is just a regular function that receives the connection
  and the request parameters as arguments. The connection is a
  `Plug.Conn` struct, as specified by the Plug library.

  ## Connection

  A controller by default provides many convenience functions for
  manipulating the connection, rendering templates, and more.

  Those functions are imported from two modules:

    * `Plug.Conn` - a bunch of low-level functions to work with
      the connection

    * `Phoenix.Controller` - functions provided by Phoenix
      to support rendering, and other Phoenix specific behaviour

  ## Rendering and layouts

  One of the main features provided by controllers is the ability
  to do content negotiation and render templates based on
  information sent by the client. Read `render/3` to learn more.

  It is also important to not confuse `Phoenix.Controller.render/3`
  with `Phoenix.View.render/3` in the long term. The former expects
  a connection and relies on content negotiation while the latter is
  connection-agnostic and typically invoked from your views.

  ## Plug pipeline

  As with routers, controllers also have their own plug pipeline.
  However, different from routers, controllers have a single pipeline:

      defmodule MyApp.UserController do
        use MyApp.Web, :controller

        plug :authenticate, usernames: ["jose", "eric", "sonny"]

        def show(conn, params) do
          # authenticated users only
        end

        defp authenticate(conn, options) do
          if get_session(conn, :username) in options[:usernames] do
            conn
          else
            conn |> redirect(Router.root_path) |> halt
          end
        end
      end

  Check `Phoenix.Controller.Pipeline` for more information on `plug/2`
  and how to customize the plug pipeline.

  ## Options

  When used, the controller supports the following options:

    * `:namespace` - sets the namespace to properly inflect
      the layout view. By default it uses the base alias
      in your controller name

    * `:log` - the level to log. When false, disables controller
      logging

  ## Overriding `action/2` for custom arguments

  Phoenix inject an `action/2` plug in your controller which calls the
  function matched from the router. By default, it passes the conn and params.
  In some cases, overriding the `action/2` plug in your controller is a
  useful way to inject certain argument to your actions that you
  would otherwise need to fetch off the connection repeatedly. For example,
  imagine if you stored a `conn.assigns.current_user` in the connection
  and wanted quick access to the user for every action in your controller:

    def action(conn, _) do
      apply(__MODULE__, action_name(conn), [conn,
                                            conn.params,
                                            conn.assigns.current_user])
    end

    def index(conn, _params, user) do
      videos = Repo.all(user_videos(user))
      ...
    end

    def delete(conn, %{"id" => id}, user) do
      video = Repo.get!(user_videos(user), id)
      ...
    end
  """
  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do
      import Plug.Conn
      import Phoenix.Controller

      use Phoenix.Controller.Pipeline

      plug Phoenix.Controller.Logger, opts
      plug :put_new_layout, {Phoenix.Controller.__layout__(__MODULE__, opts), :app}
      plug :put_new_view, Phoenix.Controller.__view__(__MODULE__)
    end
  end

  @doc """
  Returns the action name as an atom, raises if unavailable.
  """
  @spec action_name(Plug.Conn.t) :: atom
  def action_name(conn), do: conn.private.phoenix_action

  @doc """
  Returns the controller module as an atom, raises if unavailable.
  """
  @spec controller_module(Plug.Conn.t) :: atom
  def controller_module(conn), do: conn.private.phoenix_controller

  @doc """
  Returns the router module as an atom, raises if unavailable.
  """
  @spec router_module(Plug.Conn.t) :: atom
  def router_module(conn), do: conn.private.phoenix_router

  @doc """
  Returns the endpoint module as an atom, raises if unavailable.
  """
  @spec endpoint_module(Plug.Conn.t) :: atom
  def endpoint_module(conn), do: conn.private.phoenix_endpoint

  @doc """
  Returns the template name rendered in the view as a string
  (or nil if no template was rendered).
  """
  @spec view_template(Plug.Conn.t) :: binary | nil
  def view_template(conn), do: conn.private[:phoenix_template]

  defp get_json_encoder do
    Application.get_env(:phoenix, :format_encoders)
    |> Keyword.get(:json, Poison)
  end

  @doc """
  Sends JSON response.

  It uses the configured `:format_encoders` under the `:phoenix`
  application for `:json` to pick up the encoder module.

  ## Examples

      iex> json conn, %{id: 123}

  """
  @spec json(Plug.Conn.t, term) :: Plug.Conn.t
  def json(conn, data) do
    encoder = get_json_encoder()

    send_resp(conn, conn.status || 200, "application/json", encoder.encode_to_iodata!(data))
  end

  @doc """
  A plug that may convert a JSON response into a JSONP one.

  In case a JSON response is returned, it will be converted
  to a JSONP as long as the callback field is present in
  the query string. The callback field itself defaults to
  "callback" but may be configured with the callback option.

  In case there is no callback or the response is not encoded
  in JSON format, it is a no-op.

  Only alphanumeric characters and underscore are allowed in the
  callback name. Otherwise an exception is raised.

  ## Examples

      # Will convert JSON to JSONP if callback=someFunction is given
      plug :allow_jsonp

      # Will convert JSON to JSONP if cb=someFunction is given
      plug :allow_jsonp, callback: "cb"

  """
  @spec allow_jsonp(Plug.Conn.t, Keyword.t) :: Plug.Conn.t
  def allow_jsonp(conn, opts \\ []) do
    callback = Keyword.get(opts, :callback, "callback")
    case Map.fetch(conn.query_params, callback) do
      :error    -> conn
      {:ok, ""} -> conn
      {:ok, cb} ->
        validate_jsonp_callback!(cb)
        register_before_send(conn, fn conn ->
          if json_response?(conn) do
            conn
            |> put_resp_header("content-type", "application/javascript")
            |> resp(conn.status, jsonp_body(conn.resp_body, cb))
          else
            conn
          end
        end)
    end
  end

  defp json_response?(conn) do
    case get_resp_header(conn, "content-type") do
      ["application/json;" <> _] -> true
      ["application/json"] -> true
      _ -> false
    end
  end

  defp jsonp_body(data, callback) do
    body =
      data
      |> IO.iodata_to_binary()
      |> String.replace(<<0x2028::utf8>>, "\\u2028")
      |> String.replace(<<0x2029::utf8>>, "\\u2029")

    "/**/ typeof #{callback} === 'function' && #{callback}(#{body});"
  end

  defp validate_jsonp_callback!(<<h, t::binary>>)
    when h in ?0..?9 or h in ?A..?Z or h in ?a..?z or h == ?_,
    do: validate_jsonp_callback!(t)
  defp validate_jsonp_callback!(<<>>), do: :ok
  defp validate_jsonp_callback!(_),
    do: raise(ArgumentError, "the JSONP callback name contains invalid characters")

  @doc """
  Sends text response.

  ## Examples

      iex> text conn, "hello"

      iex> text conn, :implements_to_string

  """
  @spec text(Plug.Conn.t, String.Chars.t) :: Plug.Conn.t
  def text(conn, data) do
    send_resp(conn, conn.status || 200, "text/plain", to_string(data))
  end

  @doc """
  Sends html response.

  ## Examples

      iex> html conn, "..."

  """
  @spec html(Plug.Conn.t, iodata) :: Plug.Conn.t
  def html(conn, data) do
    send_resp(conn, conn.status || 200, "text/html", data)
  end

  @doc """
  Sends redirect response to the given url.

  For security, `:to` only accepts paths. Use the `:external`
  option to redirect to any URL.

  ## Examples

      iex> redirect conn, to: "/login"

      iex> redirect conn, external: "http://elixir-lang.org"

  """
  def redirect(conn, opts) when is_list(opts) do
    url  = url(opts)
    html = Plug.HTML.html_escape(url)
    body = "You are being redirected."

    conn
    |> put_resp_header("location", url)
    |> send_resp(conn.status || 302, "text/html", body)
  end

  defp url(opts) do
    cond do
      to = opts[:to] ->
        case to do
          "//" <> _ -> raise_invalid_url()
          "/" <> _  -> to
          _         -> raise_invalid_url()
        end
      external = opts[:external] ->
        external
      true ->
        raise ArgumentError, "expected :to or :external option in redirect/2"
    end
  end
  defp raise_invalid_url do
    raise ArgumentError, "the :to option in redirect expects a path"
  end

  @doc """
  Stores the view for rendering.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_view(Plug.Conn.t, atom) :: Plug.Conn.t
  def put_view(%Plug.Conn{state: state} = conn, module) when state in @unsent do
    put_private(conn, :phoenix_view, module)
  end

  def put_view(_conn, _module), do: raise AlreadySentError

  @doc """
  Stores the view for rendering if one was not stored yet.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_new_view(Plug.Conn.t, atom) :: Plug.Conn.t
  def put_new_view(%Plug.Conn{state: state} = conn, module)
      when state in @unsent do
    update_in conn.private, &Map.put_new(&1, :phoenix_view, module)
  end

  def put_new_view(_conn, _module) do
    raise Plug.Conn.AlreadySentError
  end

  @doc """
  Retrieves the current view.
  """
  @spec view_module(Plug.Conn.t) :: atom
  def view_module(conn) do
    conn.private.phoenix_view
  end

  @doc """
  Stores the layout for rendering.

  The layout must be a tuple, specifying the layout view and the layout
  name, or false. In case a previous layout is set, `put_layout` also
  accepts the layout name to be given as a string or as an atom. If a
  string, it must contain the format. Passing an atom means the layout
  format will be found at rendering time, similar to the template in
  `render/3`. It can also be set to `false`. In this case, no layout
  would be used.

  ## Examples

      iex> layout(conn)
      false

      iex> conn = put_layout conn, {AppView, "application"}
      iex> layout(conn)
      {AppView, "application"}

      iex> conn = put_layout conn, "print"
      iex> layout(conn)
      {AppView, "print"}

      iex> conn = put_layout :print
      iex> layout(conn)
      {AppView, :print}

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_layout(Plug.Conn.t, {atom, binary} | binary | false) :: Plug.Conn.t
  def put_layout(%Plug.Conn{state: state} = conn, layout) do
    if state in @unsent do
      _put_layout(conn, layout)
    else
      raise Plug.Conn.AlreadySentError
    end
  end

  def _put_layout(conn, layout)

  def _put_layout(conn, false) do
    put_private(conn, :phoenix_layout, false)
  end

  def _put_layout(conn, {mod, layout}) when is_atom(mod) do
    put_private(conn, :phoenix_layout, {mod, layout})
  end

  def _put_layout(conn, layout) when is_binary(layout) or is_atom(layout) do
    update_in conn.private, fn private ->
      case Map.get(private, :phoenix_layout, false) do
        {mod, _} -> Map.put(private, :phoenix_layout, {mod, layout})
        false    -> raise "cannot use put_layout/2 with atom/binary when layout is false, use a tuple instead"
      end
    end
  end

  @doc """
  Stores the layout for rendering if one was not stored yet.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_new_layout(Plug.Conn.t, {atom, binary} | false) :: Plug.Conn.t
  def put_new_layout(%Plug.Conn{state: state} = conn, layout)
      when (is_tuple(layout) and tuple_size(layout) == 2) or layout == false do
    if state in @unsent do
      update_in conn.private, &Map.put_new(&1, :phoenix_layout, layout)
    else
      raise AlreadySentError
    end
  end

  @doc """
  Sets which formats have a layout when rendering.

  ## Examples

      iex> layout_formats conn
      ["html"]

      iex> put_layout_formats conn, ["html", "mobile"]
      iex> layout_formats conn
      ["html", "mobile"]

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_layout_formats(Plug.Conn.t, [String.t]) :: Plug.Conn.t
  def put_layout_formats(%Plug.Conn{state: state} = conn, formats)
      when state in @unsent and is_list(formats) do
    put_private(conn, :phoenix_layout_formats, formats)
  end

  def put_layout_formats(_conn, _formats) do
    raise Plug.Conn.AlreadySentError
  end

  @doc """
  Retrieves current layout formats.
  """
  @spec layout_formats(Plug.Conn.t) :: [String.t]
  def layout_formats(conn) do
    Map.get(conn.private, :phoenix_layout_formats, ~w(html))
  end

  @doc """
  Retrieves the current layout.
  """
  @spec layout(Plug.Conn.t) :: {atom, String.t} | false
  def layout(conn), do: conn.private |> Map.get(:phoenix_layout, false)

  @doc """
  Render the given template or the default template
  specified by the current action with the given assigns.

  See `render/3` for more information.
  """
  @spec render(Plug.Conn.t, Dict.t | binary | atom) :: Plug.Conn.t
  def render(conn, template_or_assigns \\ [])

  def render(conn, template) when is_binary(template) or is_atom(template) do
    render(conn, template, [])
  end

  def render(conn, assigns) do
    render(conn, action_name(conn), assigns)
  end

  @doc """
  Renders the given `template` and `assigns` based on the `conn` information.

  Once the template is rendered, the template format is set as the response
  content type (for example, an HTML template will set "text/html" as response
  content type) and the data is sent to the client with default status of 200.

  ## Arguments

    * `conn` - the `Plug.Conn` struct

    * `template` - which may be an atom or a string. If an atom, like `:index`,
      it will render a template with the same format as the one returned by
      `get_format/1`. For example, for an HTML request, it will render
      the "index.html" template. If the template is a string, it must contain
      the extension too, like "index.json"

    * `assigns` - a dictionary with the assigns to be used in the view. Those
      assigns are merged and have higher precedence than the connection assigns
      (`conn.assigns`)

  ## Examples

      defmodule MyApp.UserController do
        use Phoenix.Controller

        def show(conn, _params) do
          render conn, "show.html", message: "Hello"
        end
      end

  The example above renders a template "show.html" from the `MyApp.UserView`
  and sets the response content type to "text/html".

  In many cases, you may want the template format to be set dynamically based
  on the request. To do so, you can pass the template name as an atom (without
  the extension):

      def show(conn, _params) do
        render conn, :show, message: "Hello"
      end

  In order for the example above to work, we need to do content negotiation with
  the accepts plug before rendering. You can do so by adding the following to your
  pipeline (in the router):

      plug :accepts, ["html"]

  ## Views

  By default, Controllers render templates in a view with a similar name to the
  controller. For example, `MyApp.UserController` will render templates inside
  the `MyApp.UserView`. This information can be changed any time by using
  `render/3`, `render/4` or the `put_view/2` function:

      def show(conn, _params) do
        render(conn, MyApp.SpecialView, :show, message: "Hello")
      end

      def show(conn, _params) do
        conn
        |> put_view(MyApp.SpecialView)
        |> render(:show, message: "Hello")
      end

  `put_view/2` can also be used as a plug:

      defmodule MyApp.UserController do
        use Phoenix.Controller

        plug :put_view, MyApp.SpecialView

        def show(conn, _params) do
          render conn, :show, message: "Hello"
        end
      end

  ## Layouts

  Templates are often rendered inside layouts. By default, Phoenix
  will render layouts for html requests. For example:

      defmodule MyApp.UserController do
        use Phoenix.Controller

        def show(conn, _params) do
          render conn, "show.html", message: "Hello"
        end
      end

  will render the  "show.html" template inside an "app.html"
  template specified in `MyApp.LayoutView`. `put_layout/2` can be used
  to change the layout, similar to how `put_view/2` can be used to change
  the view.

  `layout_formats/2` and `put_layout_formats/2` can be used to configure
  which formats support/require layout rendering (defaults to "html" only).
  """
  @spec render(Plug.Conn.t, binary | atom, Dict.t) :: Plug.Conn.t
  @spec render(Plug.Conn.t, module, binary | atom) :: Plug.Conn.t
  def render(conn, template, assigns)
    when is_atom(template) and is_list(assigns) do
    format =
      get_format(conn) ||
      raise "cannot render template #{inspect template} because conn.params[\"_format\"] is not set. " <>
            "Please set `plug :accepts, %w(html json ...)` in your pipeline."
    do_render(conn, template_name(template, format), format, assigns)
  end

  def render(conn, template, assigns) when is_binary(template) do
    case Path.extname(template) do
      "." <> format ->
        do_render(conn, template, format, assigns)
      "" ->
        raise "cannot render template #{inspect template} without format. Use an atom if the " <>
              "template format is meant to be set dynamically based on the request format"
    end
  end

  def render(conn, view, template)
    when is_atom(view) and is_binary(template) or is_atom(template) do
    render(conn, view, template, [])
  end

  @spec render(Plug.Conn.t, atom, atom | binary, Dict.t) :: Plug.Conn.t
  def render(conn, view, template, assigns)
    when is_atom(view) and is_binary(template) or is_atom(template) do
    conn
    |> put_view(view)
    |> render(template, assigns)
  end

  defp do_render(conn, template, format, assigns) do
    assigns = to_map(assigns)
    content_type = Plug.MIME.type(format)
    conn =
      conn
      |> put_private(:phoenix_template, template)
      |> prepare_assigns(assigns, format)

    view = Map.get(conn.private, :phoenix_view) ||
            raise "a view module was not specified, set one with put_view/2"
    data = Phoenix.View.render_to_iodata(view, template,
                                         Map.put(conn.assigns, :conn, conn))
    send_resp(conn, conn.status || 200, content_type, data)
  end

  @doc """
  Puts the format in the connection.

  See `get_format/1` for retrieval.
  """
  def put_format(conn, format), do: put_private(conn, :phoenix_format, format)

  @doc """
  Returns the request format, such as "json", "html".
  """
  def get_format(conn) do
    conn.private[:phoenix_format] || conn.params["_format"]
  end

  @doc """
  Scrubs the parameters from the request.

  This process is two-fold:

    * Checks to see if the `required_key` is present
    * Changes empty parameters of `required_key` (recursively) to nils

  This function is useful to remove empty strings sent
  via HTML forms. If you are providing an API, there
  is likely no need to invoke `scrub_params/2`.

  If the `required_key` is not present, it will
  raise `Phoenix.MissingParamError`.

  ## Examples

      iex> scrub_params(conn, "user")

  """
  @spec scrub_params(Plug.Conn.t, [String.t]) :: Plug.Conn.t
  def scrub_params(conn, required_key) when is_binary(required_key) do
    param = Map.get(conn.params, required_key) |> scrub_param()

    unless param do
      raise Phoenix.MissingParamError, key: required_key
    end

    params = Map.put(conn.params, required_key, param)
    %{conn | params: params}
  end

  defp scrub_param(%{__struct__: mod} = struct) when is_atom(mod) do
    struct
  end
  defp scrub_param(%{} = param) do
    Enum.reduce(param, %{}, fn({k, v}, acc) ->
      Map.put(acc, k, scrub_param(v))
    end)
  end
  defp scrub_param(param) when is_list(param) do
    Enum.map(param, &scrub_param/1)
  end
  defp scrub_param(param) do
    if scrub?(param), do: nil, else: param
  end

  defp scrub?(" " <> rest), do: scrub?(rest)
  defp scrub?(""), do: true
  defp scrub?(_), do: false

  defp prepare_assigns(conn, assigns, format) do
    layout =
      case layout(conn, assigns, format) do
        {mod, layout} -> {mod, template_name(layout, format)}
        false -> false
      end

    update_in conn.assigns,
              & &1 |> Map.merge(assigns) |> Map.put(:layout, layout)
  end

  defp layout(conn, assigns, format) do
    if format in layout_formats(conn) do
      case Map.fetch(assigns, :layout) do
        {:ok, layout} -> layout
        :error -> layout(conn)
      end
    else
      false
    end
  end

  defp to_map(assigns) when is_map(assigns), do: assigns
  defp to_map(assigns) when is_list(assigns), do: :maps.from_list(assigns)
  defp to_map(assigns), do: Dict.merge(%{}, assigns)

  defp template_name(name, format) when is_atom(name), do:
    Atom.to_string(name) <> "." <> format
  defp template_name(name, _format) when is_binary(name), do:
    name

  defp send_resp(conn, default_status, default_content_type, body) do
    conn
    |> ensure_resp_content_type(default_content_type)
    |> send_resp(conn.status || default_status, body)
  end

  defp ensure_resp_content_type(%{resp_headers: resp_headers} = conn, content_type) do
    if List.keyfind(resp_headers, "content-type", 0) do
      conn
    else
      content_type = content_type <> "; charset=utf-8"
      %{conn | resp_headers: [{"content-type", content_type}|resp_headers]}
    end
  end

  @doc """
  Enables CSRF protection.

  Currently used as a wrapper function for `Plug.CSRFProtection`
  and mainly serves as a function plug in `YourApp.Router`.

  Check `get_csrf_token/0` and `delete_csrf_token/0` for
  retrieving and deleting CSRF tokens.
  """
  def protect_from_forgery(conn, opts \\ []) do
    Plug.CSRFProtection.call(conn, Plug.CSRFProtection.init(opts))
  end

  @doc """
  Put headers that improve browser security.

  It sets the following headers:

      * x-frame-options - set to SAMEORIGIN to avoid clickjacking
        through iframes unless in the same origin
      * x-content-type-options - set to nosniff. This requires
        script and style tags to be sent with proper content type
      * x-xss-protection - set to "1; mode=block" to improve XSS
        protection on both Chrome and IE

  Custom headers may also be given.
  """
  def put_secure_browser_headers(conn, _opts \\ []) do
    merge_resp_headers(conn, [
      {"x-frame-options", "SAMEORIGIN"},
      {"x-xss-protection", "1; mode=block"},
      {"x-content-type-options", "nosniff"}
    ])
  end

  @doc """
  Gets the CSRF token.
  """
  defdelegate get_csrf_token(), to: Plug.CSRFProtection

  @doc """
  Deletes any CSRF token set.
  """
  defdelegate delete_csrf_token(), to: Plug.CSRFProtection

  @doc """
  Performs content negotiation based on the available formats.

  It receives a connection, a list of formats that the server
  is capable of rendering and then proceeds to perform content
  negotiation based on the request information. If the client
  accepts any of the given formats, the request proceeds.

  If the request contains a "_format" parameter, it is
  considered to be the format desired by the client. If no
  "_format" parameter is available, this function will parse
  the "accept" header and find a matching format accordingly.

  It is important to notice that browsers have historically
  sent bad accept headers. For this reason, this function will
  default to "html" format whenever:

    * the accepted list of arguments contains the "html" format

    * the accept header specified more than one media type preceeded
      or followed by the wildcard media type "`*/*`"

  This function raises `Phoenix.NotAcceptableError`, which is rendered
  with status 406, whenever the server cannot serve a response in any
  of the formats expected by the client.

  ## Examples

  `accepts/2` can be invoked as a function:

      iex> accepts(conn, ["html", "json"])

  or used as a plug:

      plug :accepts, ["html", "json"]
      plug :accepts, ~w(html json)

  """
  @spec accepts(Plug.Conn.t, [binary]) :: Plug.Conn.t | no_return
  def accepts(conn, [_|_] = accepted) do
    case Map.fetch(conn.params, "_format") do
      {:ok, format} ->
        handle_params_accept(conn, format, accepted)
      :error ->
        handle_header_accept(conn, get_req_header(conn, "accept"), accepted)
    end
  end

  defp handle_params_accept(conn, format, accepted) do
    if format in accepted do
      put_format(conn, format)
    else
      Logger.debug "Unknown format #{inspect format} in plug :accepts, " <>
                   "expected one of #{inspect accepted}"
      conn |> send_resp(406, "") |> halt()
    end
  end

  # In case there is no accept header or the header is */*
  # we use the first format specified in the accepts list.
  defp handle_header_accept(conn, header, [first|_]) when header == [] or header == ["*/*"] do
    put_format(conn, first)
  end

  # In case there is a header, we need to parse it.
  # But before we check for */* because if one exists and we serve html,
  # we unfortunately need to assume it is a browser sending us a request.
  defp handle_header_accept(conn, [header|_], accepted) do
    if header =~ "*/*" and "html" in accepted do
      put_format(conn, "html")
    else
      parse_header_accept(conn, String.split(header, ","), [], accepted)
    end
  end

  defp parse_header_accept(conn, [h|t], acc, accepted) do
    case Plug.Conn.Utils.media_type(h) do
      {:ok, type, subtype, args} ->
        exts = parse_exts(type <> "/" <> subtype)
        q    = parse_q(args)

        if q === 1.0 && (format = find_format(exts, accepted)) do
          put_format(conn, format)
        else
          parse_header_accept(conn, t, [{-q, exts}|acc], accepted)
        end
      :error ->
        parse_header_accept(conn, t, acc, accepted)
    end
  end

  defp parse_header_accept(conn, [], acc, accepted) do
    acc
    |> Enum.sort()
    |> Enum.find_value(&parse_header_accept(conn, &1, accepted))
    |> Kernel.||(refuse(conn, accepted))
  end

  defp parse_header_accept(conn, {_, exts}, accepted) do
    if format = find_format(exts, accepted) do
      put_format(conn, format)
    end
  end

  defp parse_q(args) do
    case Map.fetch(args, "q") do
      {:ok, float} ->
        case Float.parse(float) do
          {float, _} -> float
          :error -> 1.0
        end
      :error ->
        1.0
    end
  end

  defp parse_exts("*/*" = type), do: type
  defp parse_exts(type),         do: Plug.MIME.extensions(type)

  defp find_format("*/*", accepted), do: Enum.fetch!(accepted, 0)
  defp find_format(exts, accepted),  do: Enum.find(exts, &(&1 in accepted))

  defp refuse(conn, accepted) do
    Logger.debug "No supported media type in accept header in plug :accepts, " <>
                 "expected one of #{inspect accepted}"
    conn |> send_resp(406, "") |> halt()
  end

  @doc """
  Fetches the flash storage.
  """
  def fetch_flash(conn, _opts \\ []) do
    flash = get_session(conn, "phoenix_flash") || %{}
    conn  = persist_flash(conn, flash)

    register_before_send conn, fn conn ->
      flash = conn.private.phoenix_flash

      cond do
        map_size(flash) == 0 ->
          conn
        conn.status in 300..308 ->
          put_session(conn, "phoenix_flash", flash)
        true ->
          delete_session(conn, "phoenix_flash")
      end
    end
  end

  @doc """
  Persists a value in flash.

  Returns the updated connection.

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn, :info)
      "Welcome Back!"

  """
  def put_flash(conn, key, message) do
    persist_flash(conn, Map.put(get_flash(conn), flash_key(key), message))
  end

  @doc """
  Returns a previously set flash message or nil.

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn)
      %{"info" => "Welcome Back!"}

  """
  def get_flash(conn) do
    Map.get(conn.private, :phoenix_flash) ||
      raise ArgumentError, message: "flash not fetched, call fetch_flash/2"
  end

  @doc """
  Returns a message from flash by key

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn, :info)
      "Welcome Back!"

  """
  def get_flash(conn, key) do
    get_flash(conn)[flash_key(key)]
  end

  @doc """
  Clears all flash messages.
  """
  def clear_flash(conn) do
    persist_flash(conn, %{})
  end

  defp flash_key(binary) when is_binary(binary), do: binary
  defp flash_key(atom) when is_atom(atom), do: Atom.to_string(atom)

  defp persist_flash(conn, value) do
    put_private(conn, :phoenix_flash, value)
  end

  @doc false
  def __view__(controller_module) do
    controller_module
    |> Phoenix.Naming.unsuffix("Controller")
    |> Kernel.<>("View")
    |> String.to_atom()
  end

  @doc false
  def __layout__(controller_module, opts) do
    namespace =
      if given = Keyword.get(opts, :namespace) do
        given
      else
        controller_module
        |> Atom.to_string()
        |> String.split(".")
        |> Enum.drop(-1)
        |> Enum.take(2)
        |> Module.concat()
      end
    Module.concat(namespace, "LayoutView")
  end
end

defmodule Phoenix.Controller do
  import Plug.Conn
  alias Plug.Conn.AlreadySentError

  require Logger

  @unsent [:unset, :set]

  @moduledoc """
  Controllers are used to group common functionality in the same
  (pluggable) module.

  For example, the route:

      get "/users/:id", MyApp.UserController, :show

  will invoke the `show/2` action in the `MyApp.UserController`:

      defmodule MyApp.UserController do
        use MyApp.Web, :controller

        def show(conn, %{"id" => id}) do
          user = Repo.get(User, id)
          render conn, "show.html", user: user
        end
      end

  An action is just a regular function that receives the connection
  and the request parameters as arguments. The connection is a
  `Plug.Conn` struct, as specified by the Plug library.

  ## Connection

  A controller by default provides many convenience functions for
  manipulating the connection, rendering templates, and more.

  Those functions are imported from two modules:

    * `Plug.Conn` - a bunch of low-level functions to work with
      the connection

    * `Phoenix.Controller` - functions provided by Phoenix
      to support rendering, and other Phoenix specific behaviour

  ## Rendering and layouts

  One of the main features provided by controllers is the ability
  to do content negotiation and render templates based on
  information sent by the client. Read `render/3` to learn more.

  It is also important to not confuse `Phoenix.Controller.render/3`
  with `Phoenix.View.render/3` in the long term. The former expects
  a connection and relies on content negotiation while the latter is
  connection-agnostic and typically invoked from your views.

  ## Plug pipeline

  As with routers, controllers also have their own plug pipeline.
  However, different from routers, controllers have a single pipeline:

      defmodule MyApp.UserController do
        use MyApp.Web, :controller

        plug :authenticate, usernames: ["jose", "eric", "sonny"]

        def show(conn, params) do
          # authenticated users only
        end

        defp authenticate(conn, options) do
          if get_session(conn, :username) in options[:usernames] do
            conn
          else
            conn |> redirect(Router.root_path) |> halt
          end
        end
      end

  Check `Phoenix.Controller.Pipeline` for more information on `plug/2`
  and how to customize the plug pipeline.

  ## Options

  When used, the controller supports the following options:

    * `:namespace` - sets the namespace to properly inflect
      the layout view. By default it uses the base alias
      in your controller name

    * `:log` - the level to log. When false, disables controller
      logging
  """
  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do
      import Plug.Conn
      import Phoenix.Controller

      use Phoenix.Controller.Pipeline

      plug Phoenix.Controller.Logger, opts
      plug :put_new_layout, {Phoenix.Controller.__layout__(__MODULE__, opts), :app}
      plug :put_new_view, Phoenix.Controller.__view__(__MODULE__)
    end
  end

  @doc """
  Returns the action name as an atom, raises if unavailable.
  """
  @spec action_name(Plug.Conn.t) :: atom
  def action_name(conn), do: conn.private.phoenix_action

  @doc """
  Returns the controller module as an atom, raises if unavailable.
  """
  @spec controller_module(Plug.Conn.t) :: atom
  def controller_module(conn), do: conn.private.phoenix_controller

  @doc """
  Returns the router module as an atom, raises if unavailable.
  """
  @spec router_module(Plug.Conn.t) :: atom
  def router_module(conn), do: conn.private.phoenix_router

  @doc """
  Returns the endpoint module as an atom, raises if unavailable.
  """
  @spec endpoint_module(Plug.Conn.t) :: atom
  def endpoint_module(conn), do: conn.private.phoenix_endpoint

  @doc """
  Returns the template name rendered in the view as a string
  (or nil if no template was rendered).
  """
  @spec view_template(Plug.Conn.t) :: binary | nil
  def view_template(conn), do: conn.private[:phoenix_template]

  defp get_json_encoder do
    Application.get_env(:phoenix, :format_encoders)
    |> Keyword.get(:json, Poison)
  end

  @doc """
  Sends JSON response.

  It uses the configured `:format_encoders` under the `:phoenix`
  application for `:json` to pick up the encoder module.

  ## Examples

      iex> json conn, %{id: 123}

  """
  @spec json(Plug.Conn.t, term) :: Plug.Conn.t
  def json(conn, data) do
    encoder = get_json_encoder()

    send_resp(conn, conn.status || 200, "application/json", encoder.encode_to_iodata!(data))
  end

  @doc """
  A plug that may convert a JSON response into a JSONP one.

  In case a JSON response is returned, it will be converted
  to a JSONP as long as the callback field is present in
  the query string. The callback field itself defaults to
  "callback" but may be configured with the callback option.

  In case there is no callback or the response is not encoded
  in JSON format, it is a no-op.

  Only alphanumeric characters and underscore are allowed in the
  callback name. Otherwise an exception is raised.

  ## Examples

      # Will convert JSON to JSONP if callback=someFunction is given
      plug :allow_jsonp

      # Will convert JSON to JSONP if cb=someFunction is given
      plug :allow_jsonp, callback: "cb"

  """
  @spec allow_jsonp(Plug.Conn.t, Keyword.t) :: Plug.Conn.t
  def allow_jsonp(conn, opts \\ []) do
    callback = Keyword.get(opts, :callback, "callback")
    case Map.fetch(conn.query_params, callback) do
      :error    -> conn
      {:ok, ""} -> conn
      {:ok, cb} ->
        validate_jsonp_callback!(cb)
        register_before_send(conn, fn conn ->
          if json_response?(conn) do
            conn
            |> put_resp_header("content-type", "application/javascript")
            |> resp(conn.status, jsonp_body(conn.resp_body, cb))
          else
            conn
          end
        end)
    end
  end

  defp json_response?(conn) do
    case get_resp_header(conn, "content-type") do
      ["application/json;" <> _] -> true
      ["application/json"] -> true
      _ -> false
    end
  end

  defp jsonp_body(data, callback) do
    body =
      data
      |> IO.iodata_to_binary()
      |> String.replace(<<0x2028::utf8>>, "\\u2028")
      |> String.replace(<<0x2029::utf8>>, "\\u2029")

    "/**/ typeof #{callback} === 'function' && #{callback}(#{body});"
  end

  defp validate_jsonp_callback!(<<h, t::binary>>)
    when h in ?0..?9 or h in ?A..?Z or h in ?a..?z or h == ?_,
    do: validate_jsonp_callback!(t)
  defp validate_jsonp_callback!(<<>>), do: :ok
  defp validate_jsonp_callback!(_),
    do: raise(ArgumentError, "the JSONP callback name contains invalid characters")

  @doc """
  Sends text response.

  ## Examples

      iex> text conn, "hello"

      iex> text conn, :implements_to_string

  """
  @spec text(Plug.Conn.t, String.Chars.t) :: Plug.Conn.t
  def text(conn, data) do
    send_resp(conn, conn.status || 200, "text/plain", to_string(data))
  end

  @doc """
  Sends html response.

  ## Examples

      iex> html conn, "..."

  """
  @spec html(Plug.Conn.t, iodata) :: Plug.Conn.t
  def html(conn, data) do
    send_resp(conn, conn.status || 200, "text/html", data)
  end

  @doc """
  Sends redirect response to the given url.

  For security, `:to` only accepts paths. Use the `:external`
  option to redirect to any URL.

  ## Examples

      iex> redirect conn, to: "/login"

      iex> redirect conn, external: "http://elixir-lang.org"

  """
  def redirect(conn, opts) when is_list(opts) do
    url  = url(opts)
    html = Plug.HTML.html_escape(url)
    body = "You are being redirected."

    conn
    |> put_resp_header("location", url)
    |> send_resp(conn.status || 302, "text/html", body)
  end

  defp url(opts) do
    cond do
      to = opts[:to] ->
        case to do
          "//" <> _ -> raise_invalid_url()
          "/" <> _  -> to
          _         -> raise_invalid_url()
        end
      external = opts[:external] ->
        external
      true ->
        raise ArgumentError, "expected :to or :external option in redirect/2"
    end
  end
  defp raise_invalid_url do
    raise ArgumentError, "the :to option in redirect expects a path"
  end

  @doc """
  Stores the view for rendering.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_view(Plug.Conn.t, atom) :: Plug.Conn.t
  def put_view(%Plug.Conn{state: state} = conn, module) when state in @unsent do
    put_private(conn, :phoenix_view, module)
  end

  def put_view(_conn, _module), do: raise AlreadySentError

  @doc """
  Stores the view for rendering if one was not stored yet.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_new_view(Plug.Conn.t, atom) :: Plug.Conn.t
  def put_new_view(%Plug.Conn{state: state} = conn, module)
      when state in @unsent do
    update_in conn.private, &Map.put_new(&1, :phoenix_view, module)
  end

  def put_new_view(_conn, _module) do
    raise Plug.Conn.AlreadySentError
  end

  @doc """
  Retrieves the current view.
  """
  @spec view_module(Plug.Conn.t) :: atom
  def view_module(conn) do
    conn.private.phoenix_view
  end

  @doc """
  Stores the layout for rendering.

  The layout must be a tuple, specifying the layout view and the layout
  name, or false. In case a previous layout is set, `put_layout` also
  accepts the layout name to be given as a string or as an atom. If a
  string, it must contain the format. Passing an atom means the layout
  format will be found at rendering time, similar to the template in
  `render/3`. It can also be set to `false`. In this case, no layout
  would be used.

  ## Examples

      iex> layout(conn)
      false

      iex> conn = put_layout conn, {AppView, "application"}
      iex> layout(conn)
      {AppView, "application"}

      iex> conn = put_layout conn, "print"
      iex> layout(conn)
      {AppView, "print"}

      iex> conn = put_layout :print
      iex> layout(conn)
      {AppView, :print}

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_layout(Plug.Conn.t, {atom, binary} | binary | false) :: Plug.Conn.t
  def put_layout(%Plug.Conn{state: state} = conn, layout) do
    if state in @unsent do
      _put_layout(conn, layout)
    else
      raise Plug.Conn.AlreadySentError
    end
  end

  def _put_layout(conn, layout)

  def _put_layout(conn, false) do
    put_private(conn, :phoenix_layout, false)
  end

  def _put_layout(conn, {mod, layout}) when is_atom(mod) do
    put_private(conn, :phoenix_layout, {mod, layout})
  end

  def _put_layout(conn, layout) when is_binary(layout) or is_atom(layout) do
    update_in conn.private, fn private ->
      case Map.get(private, :phoenix_layout, false) do
        {mod, _} -> Map.put(private, :phoenix_layout, {mod, layout})
        false    -> raise "cannot use put_layout/2 with atom/binary when layout is false, use a tuple instead"
      end
    end
  end

  @doc """
  Stores the layout for rendering if one was not stored yet.

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_new_layout(Plug.Conn.t, {atom, binary} | false) :: Plug.Conn.t
  def put_new_layout(%Plug.Conn{state: state} = conn, layout)
      when (is_tuple(layout) and tuple_size(layout) == 2) or layout == false do
    if state in @unsent do
      update_in conn.private, &Map.put_new(&1, :phoenix_layout, layout)
    else
      raise AlreadySentError
    end
  end

  @doc """
  Sets which formats have a layout when rendering.

  ## Examples

      iex> layout_formats conn
      ["html"]

      iex> put_layout_formats conn, ["html", "mobile"]
      iex> layout_formats conn
      ["html", "mobile"]

  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
  """
  @spec put_layout_formats(Plug.Conn.t, [String.t]) :: Plug.Conn.t
  def put_layout_formats(%Plug.Conn{state: state} = conn, formats)
      when state in @unsent and is_list(formats) do
    put_private(conn, :phoenix_layout_formats, formats)
  end

  def put_layout_formats(_conn, _formats) do
    raise Plug.Conn.AlreadySentError
  end

  @doc """
  Retrieves current layout formats.
  """
  @spec layout_formats(Plug.Conn.t) :: [String.t]
  def layout_formats(conn) do
    Map.get(conn.private, :phoenix_layout_formats, ~w(html))
  end

  @doc """
  Retrieves the current layout.
  """
  @spec layout(Plug.Conn.t) :: {atom, String.t} | false
  def layout(conn), do: conn.private |> Map.get(:phoenix_layout, false)

  @doc """
  Render the given template or the default template
  specified by the current action with the given assigns.

  See `render/3` for more information.
  """
  @spec render(Plug.Conn.t, Dict.t | binary | atom) :: Plug.Conn.t
  def render(conn, template_or_assigns \\ [])

  def render(conn, template) when is_binary(template) or is_atom(template) do
    render(conn, template, [])
  end

  def render(conn, assigns) do
    render(conn, action_name(conn), assigns)
  end

  @doc """
  Renders the given `template` and `assigns` based on the `conn` information.

  Once the template is rendered, the template format is set as the response
  content type (for example, an HTML template will set "text/html" as response
  content type) and the data is sent to the client with default status of 200.

  ## Arguments

    * `conn` - the `Plug.Conn` struct

    * `template` - which may be an atom or a string. If an atom, like `:index`,
      it will render a template with the same format as the one returned by
      `get_format/1`. For example, for an HTML request, it will render
      the "index.html" template. If the template is a string, it must contain
      the extension too, like "index.json"

    * `assigns` - a dictionary with the assigns to be used in the view. Those
      assigns are merged and have higher precedence than the connection assigns
      (`conn.assigns`)

  ## Examples

      defmodule MyApp.UserController do
        use Phoenix.Controller

        def show(conn, _params) do
          render conn, "show.html", message: "Hello"
        end
      end

  The example above renders a template "show.html" from the `MyApp.UserView`
  and sets the response content type to "text/html".

  In many cases, you may want the template format to be set dynamically based
  on the request. To do so, you can pass the template name as an atom (without
  the extension):

      def show(conn, _params) do
        render conn, :show, message: "Hello"
      end

  In order for the example above to work, we need to do content negotiation with
  the accepts plug before rendering. You can do so by adding the following to your
  pipeline (in the router):

      plug :accepts, ["html"]

  ## Views

  By default, Controllers render templates in a view with a similar name to the
  controller. For example, `MyApp.UserController` will render templates inside
  the `MyApp.UserView`. This information can be changed any time by using
  `render/3`, `render/4` or the `put_view/2` function:

      def show(conn, _params) do
        render(conn, MyApp.SpecialView, :show, message: "Hello")
      end

      def show(conn, _params) do
        conn
        |> put_view(MyApp.SpecialView)
        |> render(:show, message: "Hello")
      end

  `put_view/2` can also be used as a plug:

      defmodule MyApp.UserController do
        use Phoenix.Controller

        plug :put_view, MyApp.SpecialView

        def show(conn, _params) do
          render conn, :show, message: "Hello"
        end
      end

  ## Layouts

  Templates are often rendered inside layouts. By default, Phoenix
  will render layouts for html requests. For example:

      defmodule MyApp.UserController do
        use Phoenix.Controller

        def show(conn, _params) do
          render conn, "show.html", message: "Hello"
        end
      end

  will render the  "show.html" template inside an "app.html"
  template specified in `MyApp.LayoutView`. `put_layout/2` can be used
  to change the layout, similar to how `put_view/2` can be used to change
  the view.

  `layout_formats/2` and `put_layout_formats/2` can be used to configure
  which formats support/require layout rendering (defaults to "html" only).
  """
  @spec render(Plug.Conn.t, binary | atom, Dict.t) :: Plug.Conn.t
  @spec render(Plug.Conn.t, module, binary | atom) :: Plug.Conn.t
  def render(conn, template, assigns)
    when is_atom(template) and is_list(assigns) do
    format =
      get_format(conn) ||
      raise "cannot render template #{inspect template} because conn.params[\"_format\"] is not set. " <>
            "Please set `plug :accepts, %w(html json ...)` in your pipeline."
    do_render(conn, template_name(template, format), format, assigns)
  end

  def render(conn, template, assigns) when is_binary(template) do
    case Path.extname(template) do
      "." <> format ->
        do_render(conn, template, format, assigns)
      "" ->
        raise "cannot render template #{inspect template} without format. Use an atom if the " <>
              "template format is meant to be set dynamically based on the request format"
    end
  end

  def render(conn, view, template)
    when is_atom(view) and is_binary(template) or is_atom(template) do
    render(conn, view, template, [])
  end

  @spec render(Plug.Conn.t, atom, atom | binary, Dict.t) :: Plug.Conn.t
  def render(conn, view, template, assigns)
    when is_atom(view) and is_binary(template) or is_atom(template) do
    conn
    |> put_view(view)
    |> render(template, assigns)
  end

  defp do_render(conn, template, format, assigns) do
    assigns = to_map(assigns)
    content_type = Plug.MIME.type(format)
    conn =
      conn
      |> put_private(:phoenix_template, template)
      |> prepare_assigns(assigns, format)

    view = Map.get(conn.private, :phoenix_view) ||
            raise "a view module was not specified, set one with put_view/2"
    data = Phoenix.View.render_to_iodata(view, template,
                                         Map.put(conn.assigns, :conn, conn))
    send_resp(conn, conn.status || 200, content_type, data)
  end

  @doc """
  Puts the format in the connection.

  See `get_format/1` for retrieval.
  """
  def put_format(conn, format), do: put_private(conn, :phoenix_format, format)

  @doc """
  Returns the request format, such as "json", "html".
  """
  def get_format(conn) do
    conn.private[:phoenix_format] || conn.params["_format"]
  end

  @doc """
  Scrubs the parameters from the request.

  This process is two-fold:

    * Checks to see if the `required_key` is present
    * Changes empty parameters of `required_key` (recursively) to nils

  This function is useful to remove empty strings sent
  via HTML forms. If you are providing an API, there
  is likely no need to invoke `scrub_params/2`.

  If the `required_key` is not present, it will
  raise `Phoenix.MissingParamError`.

  ## Examples

      iex> scrub_params(conn, "user")

  """
  @spec scrub_params(Plug.Conn.t, [String.t]) :: Plug.Conn.t
  def scrub_params(conn, required_key) when is_binary(required_key) do
    param = Map.get(conn.params, required_key) |> scrub_param()

    unless param do
      raise Phoenix.MissingParamError, key: required_key
    end

    params = Map.put(conn.params, required_key, param)
    %{conn | params: params}
  end

  defp scrub_param(%{__struct__: mod} = struct) when is_atom(mod) do
    struct
  end
  defp scrub_param(%{} = param) do
    Enum.reduce(param, %{}, fn({k, v}, acc) ->
      Map.put(acc, k, scrub_param(v))
    end)
  end
  defp scrub_param(param) when is_list(param) do
    Enum.map(param, &scrub_param/1)
  end
  defp scrub_param(param) do
    if scrub?(param), do: nil, else: param
  end

  defp scrub?(" " <> rest), do: scrub?(rest)
  defp scrub?(""), do: true
  defp scrub?(_), do: false

  defp prepare_assigns(conn, assigns, format) do
    layout =
      case layout(conn, assigns, format) do
        {mod, layout} -> {mod, template_name(layout, format)}
        false -> false
      end

    update_in conn.assigns,
              & &1 |> Map.merge(assigns) |> Map.put(:layout, layout)
  end

  defp layout(conn, assigns, format) do
    if format in layout_formats(conn) do
      case Map.fetch(assigns, :layout) do
        {:ok, layout} -> layout
        :error -> layout(conn)
      end
    else
      false
    end
  end

  defp to_map(assigns) when is_map(assigns), do: assigns
  defp to_map(assigns) when is_list(assigns), do: :maps.from_list(assigns)
  defp to_map(assigns), do: Dict.merge(%{}, assigns)

  defp template_name(name, format) when is_atom(name), do:
    Atom.to_string(name) <> "." <> format
  defp template_name(name, _format) when is_binary(name), do:
    name

  defp send_resp(conn, default_status, default_content_type, body) do
    conn
    |> ensure_resp_content_type(default_content_type)
    |> send_resp(conn.status || default_status, body)
  end

  defp ensure_resp_content_type(%{resp_headers: resp_headers} = conn, content_type) do
    if List.keyfind(resp_headers, "content-type", 0) do
      conn
    else
      content_type = content_type <> "; charset=utf-8"
      %{conn | resp_headers: [{"content-type", content_type}|resp_headers]}
    end
  end

  @doc """
  Enables CSRF protection.

  Currently used as a wrapper function for `Plug.CSRFProtection`
  and mainly serves as a function plug in `YourApp.Router`.

  Check `get_csrf_token/0` and `delete_csrf_token/0` for
  retrieving and deleting CSRF tokens.
  """
  def protect_from_forgery(conn, opts \\ []) do
    Plug.CSRFProtection.call(conn, Plug.CSRFProtection.init(opts))
  end

  @doc """
  Put headers that improve browser security.

  It sets the following headers:

      * x-frame-options - set to SAMEORIGIN to avoid clickjacking
        through iframes unless in the same origin
      * x-content-type-options - set to nosniff. This requires
        script and style tags to be sent with proper content type
      * x-xss-protection - set to "1; mode=block" to improve XSS
        protection on both Chrome and IE

  Custom headers may also be given.
  """
  def put_secure_browser_headers(conn, _opts \\ []) do
    merge_resp_headers(conn, [
      {"x-frame-options", "SAMEORIGIN"},
      {"x-xss-protection", "1; mode=block"},
      {"x-content-type-options", "nosniff"}
    ])
  end

  @doc """
  Gets the CSRF token.
  """
  defdelegate get_csrf_token(), to: Plug.CSRFProtection

  @doc """
  Deletes any CSRF token set.
  """
  defdelegate delete_csrf_token(), to: Plug.CSRFProtection

  @doc """
  Performs content negotiation based on the available formats.

  It receives a connection, a list of formats that the server
  is capable of rendering and then proceeds to perform content
  negotiation based on the request information. If the client
  accepts any of the given formats, the request proceeds.

  If the request contains a "_format" parameter, it is
  considered to be the format desired by the client. If no
  "_format" parameter is available, this function will parse
  the "accept" header and find a matching format accordingly.

  It is important to notice that browsers have historically
  sent bad accept headers. For this reason, this function will
  default to "html" format whenever:

    * the accepted list of arguments contains the "html" format

    * the accept header specified more than one media type preceeded
      or followed by the wildcard media type "`*/*`"

  This function raises `Phoenix.NotAcceptableError`, which is rendered
  with status 406, whenever the server cannot serve a response in any
  of the formats expected by the client.

  ## Examples

  `accepts/2` can be invoked as a function:

      iex> accepts(conn, ["html", "json"])

  or used as a plug:

      plug :accepts, ["html", "json"]
      plug :accepts, ~w(html json)

  """
  @spec accepts(Plug.Conn.t, [binary]) :: Plug.Conn.t | no_return
  def accepts(conn, [_|_] = accepted) do
    case Map.fetch(conn.params, "_format") do
      {:ok, format} ->
        handle_params_accept(conn, format, accepted)
      :error ->
        handle_header_accept(conn, get_req_header(conn, "accept"), accepted)
    end
  end

  defp handle_params_accept(conn, format, accepted) do
    if format in accepted do
      put_format(conn, format)
    else
      Logger.debug "Unknown format #{inspect format} in plug :accepts, " <>
                   "expected one of #{inspect accepted}"
      conn |> send_resp(406, "") |> halt()
    end
  end

  # In case there is no accept header or the header is */*
  # we use the first format specified in the accepts list.
  defp handle_header_accept(conn, header, [first|_]) when header == [] or header == ["*/*"] do
    put_format(conn, first)
  end

  # In case there is a header, we need to parse it.
  # But before we check for */* because if one exists and we serve html,
  # we unfortunately need to assume it is a browser sending us a request.
  defp handle_header_accept(conn, [header|_], accepted) do
    if header =~ "*/*" and "html" in accepted do
      put_format(conn, "html")
    else
      parse_header_accept(conn, String.split(header, ","), [], accepted)
    end
  end

  defp parse_header_accept(conn, [h|t], acc, accepted) do
    case Plug.Conn.Utils.media_type(h) do
      {:ok, type, subtype, args} ->
        exts = parse_exts(type <> "/" <> subtype)
        q    = parse_q(args)

        if q === 1.0 && (format = find_format(exts, accepted)) do
          put_format(conn, format)
        else
          parse_header_accept(conn, t, [{-q, exts}|acc], accepted)
        end
      :error ->
        parse_header_accept(conn, t, acc, accepted)
    end
  end

  defp parse_header_accept(conn, [], acc, accepted) do
    acc
    |> Enum.sort()
    |> Enum.find_value(&parse_header_accept(conn, &1, accepted))
    |> Kernel.||(refuse(conn, accepted))
  end

  defp parse_header_accept(conn, {_, exts}, accepted) do
    if format = find_format(exts, accepted) do
      put_format(conn, format)
    end
  end

  defp parse_q(args) do
    case Map.fetch(args, "q") do
      {:ok, float} ->
        case Float.parse(float) do
          {float, _} -> float
          :error -> 1.0
        end
      :error ->
        1.0
    end
  end

  defp parse_exts("*/*" = type), do: type
  defp parse_exts(type),         do: Plug.MIME.extensions(type)

  defp find_format("*/*", accepted), do: Enum.fetch!(accepted, 0)
  defp find_format(exts, accepted),  do: Enum.find(exts, &(&1 in accepted))

  defp refuse(conn, accepted) do
    Logger.debug "No supported media type in accept header in plug :accepts, " <>
                 "expected one of #{inspect accepted}"
    conn |> send_resp(406, "") |> halt()
  end

  @doc """
  Fetches the flash storage.
  """
  def fetch_flash(conn, _opts \\ []) do
    flash = get_session(conn, "phoenix_flash") || %{}
    conn  = persist_flash(conn, flash)

    register_before_send conn, fn conn ->
      flash = conn.private.phoenix_flash

      cond do
        map_size(flash) == 0 ->
          conn
        conn.status in 300..308 ->
          put_session(conn, "phoenix_flash", flash)
        true ->
          delete_session(conn, "phoenix_flash")
      end
    end
  end

  @doc """
  Persists a value in flash.

  Returns the updated connection.

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn, :info)
      "Welcome Back!"

  """
  def put_flash(conn, key, message) do
    persist_flash(conn, Map.put(get_flash(conn), flash_key(key), message))
  end

  @doc """
  Returns a previously set flash message or nil.

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn)
      %{"info" => "Welcome Back!"}

  """
  def get_flash(conn) do
    Map.get(conn.private, :phoenix_flash) ||
      raise ArgumentError, message: "flash not fetched, call fetch_flash/2"
  end

  @doc """
  Returns a message from flash by key

  ## Examples

      iex> conn = put_flash(conn, :info, "Welcome Back!")
      iex> get_flash(conn, :info)
      "Welcome Back!"

  """
  def get_flash(conn, key) do
    get_flash(conn)[flash_key(key)]
  end

  @doc """
  Clears all flash messages.
  """
  def clear_flash(conn) do
    persist_flash(conn, %{})
  end

  defp flash_key(binary) when is_binary(binary), do: binary
  defp flash_key(atom) when is_atom(atom), do: Atom.to_string(atom)

  defp persist_flash(conn, value) do
    put_private(conn, :phoenix_flash, value)
  end

  @doc false
  def __view__(controller_module) do
    controller_module
    |> Phoenix.Naming.unsuffix("Controller")
    |> Kernel.<>("View")
    |> String.to_atom()
  end

  @doc false
  def __layout__(controller_module, opts) do
    namespace =
      if given = Keyword.get(opts, :namespace) do
        given
      else
        controller_module
        |> Atom.to_string()
        |> String.split(".")
        |> Enum.drop(-1)
        |> Enum.take(2)
        |> Module.concat()
      end
    Module.concat(namespace, "LayoutView")
  end
end


Always order batch list

Always order batch list

defmodule BorsNG.Database.Batch do
  @moduledoc """
  The database-level representation of a "batch".

  A batch is a collection of patches that are running, or will run.
  """

  @type t :: %__MODULE__{}

  use BorsNG.Database.Model
  alias BorsNG.Database.BatchState

  schema "batches" do
    belongs_to :project, Project
    field :into_branch, :string
    field :commit, :string
    field :state, BatchState
    field :last_polled, :integer
    field :timeout_at, :integer
    field :priority, :integer, default: 0
    has_many :patches, LinkPatchBatch
    timestamps()
  end

  def new(project_id, into_branch, priority \\ 0) do
    %Batch{
      into_branch: into_branch,
      project_id: project_id,
      commit: nil,
      state: :waiting,
      last_polled: DateTime.to_unix(DateTime.utc_now(), :seconds),
      priority: priority
    }
  end

  def is_empty(batch_id, repo) do
    links = LinkPatchBatch
    |> where([l], l.batch_id == ^batch_id)
    |> repo.all()
    links == []
  end

  def all_for_project(project_id) do
    from b in Batch,
      where: b.project_id == ^project_id,
      order_by: [desc: b.state]
  end

  def all_for_project(project_id, nil), do: all_for_project(project_id)

  def all_for_project(project_id, :incomplete) do
    from b in all_for_project(project_id),
      where: b.state == ^(:waiting) or b.state == ^(:running),
      order_by: [desc: b.state]
  end

  def all_for_project(project_id, :complete) do
    from b in all_for_project(project_id),
      where: b.state == ^(:ok)
        or b.state == ^(:error)
        or b.state == ^(:canceled),
      order_by: [desc: b.state]
  end

  def all_for_project(project_id, state) do
    from b in all_for_project(project_id),
      where: b.state == ^state
  end

  def all_for_patch(patch_id, state \\ nil) do
    from b in all_assoc(state),
      join: l in LinkPatchBatch, on: l.batch_id == b.id,
      where: l.patch_id == ^patch_id
  end

  def all_assoc do
    from b in Batch,
      join: p in assoc(b, :project),
      preload: [project: p]
  end

  def all_assoc(nil), do: all_assoc()

  def all_assoc(:incomplete) do
    from b in all_assoc(),
      where: b.state == ^(:waiting) or b.state == ^(:running)
  end

  def all_assoc(:complete) do
    from b in all_assoc(),
      where: b.state == ^(:ok)
        or b.state == ^(:error)
        or b.state == ^(:canceled)
  end

  def get_assoc_by_commit(project_id, commit, state \\ nil) do
    from b in all_assoc(state),
      where: b.commit == ^commit and b.project_id == ^project_id
  end

  def next_poll_is_past(batch) do
    now = DateTime.to_unix(DateTime.utc_now(), :seconds)
    next_poll_is_past(batch, now)
  end

  def next_poll_is_past(batch, now_utc_sec) do
    next = get_next_poll_unix_sec(batch)
    next < now_utc_sec
  end

  def timeout_is_past(%Batch{timeout_at: timeout_at}) do
    now = DateTime.to_unix(DateTime.utc_now(), :seconds)
    now > timeout_at
  end

  def get_next_poll_unix_sec(batch) do
    period = if batch.state == :waiting do
      batch.project.batch_delay_sec
    else
      batch.project.batch_poll_period_sec
    end
    batch.last_polled + period
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [
      :project_id,
      :commit,
      :state,
      :last_polled,
      :timeout_at,
      :priority
    ])
  end

  def changeset_raise_priority(struct, params \\ %{}) do
    struct
    |> cast(params, [
      :priority
    ])
  end
end

defmodule BorsNG.Database.Batch do
  @moduledoc """
  The database-level representation of a "batch".

  A batch is a collection of patches that are running, or will run.
  """

  @type t :: %__MODULE__{}

  use BorsNG.Database.Model
  alias BorsNG.Database.BatchState

  schema "batches" do
    belongs_to :project, Project
    field :into_branch, :string
    field :commit, :string
    field :state, BatchState
    field :last_polled, :integer
    field :timeout_at, :integer
    field :priority, :integer, default: 0
    has_many :patches, LinkPatchBatch
    timestamps()
  end

  def new(project_id, into_branch, priority \\ 0) do
    %Batch{
      into_branch: into_branch,
      project_id: project_id,
      commit: nil,
      state: :waiting,
      last_polled: DateTime.to_unix(DateTime.utc_now(), :seconds),
      priority: priority
    }
  end

  def is_empty(batch_id, repo) do
    links = LinkPatchBatch
    |> where([l], l.batch_id == ^batch_id)
    |> repo.all()
    links == []
  end

  def all_for_project(project_id) do
    from b in Batch,
      where: b.project_id == ^project_id
  end

  def all_for_project(project_id, nil), do: all_for_project(project_id)

  def all_for_project(project_id, :incomplete) do
    from b in all_for_project(project_id),
      where: b.state == ^(:waiting) or b.state == ^(:running),
      order_by: b.state
  end

  def all_for_project(project_id, :complete) do
    from b in all_for_project(project_id),
      where: b.state == ^(:ok)
        or b.state == ^(:error)
        or b.state == ^(:canceled)
  end

  def all_for_project(project_id, state) do
    from b in all_for_project(project_id),
      where: b.state == ^state
  end

  def all_for_patch(patch_id, state \\ nil) do
    from b in all_assoc(state),
      join: l in LinkPatchBatch, on: l.batch_id == b.id,
      where: l.patch_id == ^patch_id
  end

  def all_assoc do
    from b in Batch,
      join: p in assoc(b, :project),
      preload: [project: p]
  end

  def all_assoc(nil), do: all_assoc()

  def all_assoc(:incomplete) do
    from b in all_assoc(),
      where: b.state == ^(:waiting) or b.state == ^(:running)
  end

  def all_assoc(:complete) do
    from b in all_assoc(),
      where: b.state == ^(:ok)
        or b.state == ^(:error)
        or b.state == ^(:canceled)
  end

  def get_assoc_by_commit(project_id, commit, state \\ nil) do
    from b in all_assoc(state),
      where: b.commit == ^commit and b.project_id == ^project_id
  end

  def next_poll_is_past(batch) do
    now = DateTime.to_unix(DateTime.utc_now(), :seconds)
    next_poll_is_past(batch, now)
  end

  def next_poll_is_past(batch, now_utc_sec) do
    next = get_next_poll_unix_sec(batch)
    next < now_utc_sec
  end

  def timeout_is_past(%Batch{timeout_at: timeout_at}) do
    now = DateTime.to_unix(DateTime.utc_now(), :seconds)
    now > timeout_at
  end

  def get_next_poll_unix_sec(batch) do
    period = if batch.state == :waiting do
      batch.project.batch_delay_sec
    else
      batch.project.batch_poll_period_sec
    end
    batch.last_polled + period
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [
      :project_id,
      :commit,
      :state,
      :last_polled,
      :timeout_at,
      :priority
    ])
  end

  def changeset_raise_priority(struct, params \\ %{}) do
    struct
    |> cast(params, [
      :priority
    ])
  end
end