defmodule Morse do

  # Some test samples to decode.
  def base(), do: '.- .-.. .-.. ..-- -.-- --- ..- .-. ..-- -... .- ... . ..-- .- .-. . ..-- -... . .-.. --- -. --. ..-- - --- ..-- ..- ...'

  def rolled(), do: '.... - - .--. ... ---... .----- .----- .-- .-- .-- .-.-.- -.-- --- ..- - ..- -... . .-.-.- -.-. --- -- .----- .-- .- - -.-. .... ..--.. ...- .----. -.. .--.-- ..... .---- .-- ....- .-- ----. .--.-- ..... --... --. .--.-- ..... ---.. -.-. .--.-- ..... .----'

  def test1() , do: '- .... .- -. -.- ... ..-- ..-. --- .-. ..-- .- ..-- ..-. ..- -. ..-- -.-. --- ..- .-. ... . '

  def test2() , do: '-....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- .-.-.- -....- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- '


  def test3() , do: '.-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- .-.-.- -....- .-.-.- -....- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- -....- .-.-.- .-.-.- .-.-.- .-.-.- -....- ..-- .-.-.- .-.-.- -....- -....- ..-- '


  def test4(), do:  '-. -.-- - ..-- --- .-.. . -- -- . ..-- ...- .- .-.. -- .. - - .-'

  def decode(signal) do
    tree = tree()
    decode(signal, tree)
  end

  def decode([], _) do  [] end
  def decode(signal, tree) do
    case decode_char(signal, tree) do
      :no -> 
	:io.format("error : ~w\n", [Enum.take(signal, 10)])
        []
      {char, rest} ->
	[char | decode(rest, tree)]
    end
  end
  
  def decode_char([], {:node, char, _, _}), do: {char, []}

  def decode_char([?- | signal], {:node, _, long, _}) do
    decode_char(signal, long)
  end
  def decode_char([?. | signal], {:node, _, _, short}) do
    decode_char(signal, short)
  end

  # something strange
  def decode_char(_signal, :nil) do :no end

  def decode_char([?\s | _signal], {:node, :na, _, _}) do :no end

  def decode_char([?\s | signal], {:node, char, _, _}) do
    {char, signal}
  end

  ## The encoder

  def encode(text) do
    tree = tree()
    table = encode_table(tree)
    encode(text, [], table)
  end

  def encode_table(tree) do
    encode_table(tree, [], %{})
  end

  def encode_table(nil, _, map) do  map end
  def encode_table({:node, :na, long, short}, code, map) do
    map = encode_table(long, [?-|code], map)
    encode_table(short, [?.|code], map)
  end
  def encode_table({:node, char, long, short}, code, map) do
    map = Map.put(map, char, code)
    map = encode_table(long, [?-|code], map)
    encode_table(short, [?.|code], map)
  end
  
  defp encode([], all, _), do: unpack(all, [])
  defp encode([char | rest], sofar, table) do
    code = Map.get(table, char)
    encode(rest, [code | sofar], table)
  end
  
  defp unpack([], done), do: done
  defp unpack([code | rest], sofar) do
    unpack(rest, code ++ [?\s | sofar])
  end


  # Morse decoding tree.
  defp tree do
    {:node, :na,
      {:node, 116,
        {:node, 109,
          {:node, 111,
            {:node, :na, {:node, 48, nil, nil}, {:node, 57, nil, nil}},
            {:node, :na, nil, {:node, 56, nil, {:node, 58, nil, nil}}}},
          {:node, 103,
            {:node, 113, nil, nil},
            {:node, 122,
              {:node, :na, {:node, 44, nil, nil}, nil},
              {:node, 55, nil, nil}}}},
        {:node, 110,
          {:node, 107, {:node, 121, nil, nil}, {:node, 99, nil, nil}},
          {:node, 100,
            {:node, 120, nil, nil},
            {:node, 98, nil, {:node, 54, {:node, 45, nil, nil}, nil}}}}},
      {:node, 101,
        {:node, 97,
          {:node, 119,
            {:node, 106,
              {:node, 49, {:node, 47, nil, nil}, {:node, 61, nil, nil}},
              nil},
            {:node, 112,
              {:node, :na, {:node, 37, nil, nil}, {:node, 64, nil, nil}},
              nil}},
          {:node, 114,
            {:node, :na, nil, {:node, :na, {:node, 46, nil, nil}, nil}},
            {:node, 108, nil, nil}}},
        {:node, 105,
          {:node, 117,
            {:node, 32,
              {:node, 50, nil, nil},
              {:node, :na, nil, {:node, 63, nil, nil}}},
            {:node, 102, nil, nil}},
          {:node, 115,
            {:node, 118, {:node, 51, nil, nil}, nil},
            {:node, 104, {:node, 52, nil, nil}, {:node, 53, nil, nil}}}}}}
  end

end
