   use GenServer
   require Logger
   alias AmqpOne.Transport.Socket
+  alias AmqpOne.Transport.Frame
 
   @type perf_t :: :open | :begin | :attach | :flow | :transfer |
   :disposition | :detch | :end | :close

    AmqpOne.Transport.Socket.set_active_once(state.socket)
    put_in state, :state, :hdr_exch
  end
  def connection(:hdr_exch, %Frame{performative: :open} = f, state) do
    :ok = AmqpOne.Transport.Socket.send(state.socket, encode_frame(f, f.channel))
    put_in state, :state, :open_sent
  end
  def connection(:hdr_exch, {:tcp, %Frame{performative: :open} = f}, state) do
    Logger.info "Got an open frame: #{inspect f}"
    put_in state, :state, :open_rcvd
  end
  def connection(:open_rcvd, %Frame{performative: :open} = f, state) do
    :ok = AmqpOne.Transport.Socket.send(state.socket, encode_frame(f, f.channel))
    put_in state, :state, :opened
  end
  def connection(:open_sent, {:tcp, %Frame{performative: :open} = f}, state) do
    Logger.info "Got an open frame: #{inspect f}"
    put_in state, :state, :opened
  end
  def connection(:open_sent, %Frame{performative: :close} = f, state) do
    Logger.info "Got an internal close frame: #{inspect f}"
    put_in state, :state, :close_pipe
  end
  def connection(:opened, %Frame{performative: :close} = f, state) do
    Logger.info "Got an internal close frame: #{inspect f}"
    put_in state, :state, :close_sent
  end
  def connection(:open_sent, {:tcp, %Frame{performative: :close} = f}, state) do
    Logger.info "Got an close frame: #{inspect f}"
    put_in state, :state, :close_rcvd
  end
  def connection(:opened, some_frame, state) do
    Logger.info "Got any AMQP frame: #{inspect some_frame}"
    Logger.error "We shoudl send this frame to someone else"
    state
  end
  def connection(:close_sent, {:tcp, %Frame{performative: :close} = f}, state) do
    AmqpOne.Transport.Socket.close(state.socket)
    put_in state, :state, :end
  end
  def connection(:close_rcvd, %Frame{performative: :close} = f, state) do
    AmqpOne.Transport.Socket.close(state.socket)
    put_in state, :state, :end
  end
  def conncetion(:open_pipe, %Frame{performative: :close} = f, state) do
    put_in state, :state, :oc_pipe
  end
  def conncetion(:open_pipe, @amqp_header, state) do
    put_in state, :state, :open_sent
  end
  def conncetion(:close_pipe, {:tcp, %Frame{performative: :open} = f}, state) do
    Logger.info "Got an open frame: #{inspect f}"
    put_in state, :state, :close_sent
  end

    {:no_reply, new_state}
  end

  @spec connection(conn_state_t, binary | any, t) :: t
  def connection(:start, {tcp, @amqp_header}, state) do
    # this state is only relevant for being a server.
    # there is no attempt to deal with this situation for now.
    Socket.set_active_once(state.socket)
    put_in(state, :state, :hdr_rcvd)
  end
  def connection(:hdr_sent, %Frame.Open{} = f, state) do
    # we are sending an open directly after the hdr: pipelining!
    AmqpOne.Transport.Socket.send(state.socket, encode_frame(f, 0))
    put_in state, :state, :open_pipe
  end
  def connection(:hdr_sent, @amqp_header, state) do
