//
// posix_chat_client.cpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include "asio.hpp"
#include "chat_message.hpp"

#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)

using asio::ip::tcp;
namespace posix = asio::posix;

class posix_chat_client
{
public:
  posix_chat_client(asio::io_service& io_service,
      tcp::resolver::iterator endpoint_iterator)
    : socket_(io_service),
      input_(io_service, ::dup(STDIN_FILENO)),
      output_(io_service, ::dup(STDOUT_FILENO)),
      input_buffer_(chat_message::max_body_length)
  {
    asio::async_connect(socket_, endpoint_iterator,
        boost::bind(&posix_chat_client::handle_connect, this,
          asio::placeholders::error));
  }

private:

  void handle_connect(const asio::error_code& error)
  {
    if (!error)
    {
      // Read the fixed-length header of the next message from the server.
      asio::async_read(socket_,
          asio::buffer(read_msg_.data(), chat_message::header_length),
          boost::bind(&posix_chat_client::handle_read_header, this,
            asio::placeholders::error));

      // Read a line of input entered by the user.
      asio::async_read_until(input_, input_buffer_, '\n',
          boost::bind(&posix_chat_client::handle_read_input, this,
            asio::placeholders::error,
            asio::placeholders::bytes_transferred));
    }
  }

  void handle_read_header(const asio::error_code& error)
  {
    if (!error && read_msg_.decode_header())
    {
      // Read the variable-length body of the message from the server.
      asio::async_read(socket_,
          asio::buffer(read_msg_.body(), read_msg_.body_length()),
          boost::bind(&posix_chat_client::handle_read_body, this,
            asio::placeholders::error));
    }
    else
    {
      close();
    }
  }

  void handle_read_body(const asio::error_code& error)
  {
    if (!error)
    {
      // Write out the message we just received, terminated by a newline.
      static char eol[] = { '\n' };
      boost::array<asio::const_buffer, 2> buffers = {{
        asio::buffer(read_msg_.body(), read_msg_.body_length()),
        asio::buffer(eol) }};
      asio::async_write(output_, buffers,
          boost::bind(&posix_chat_client::handle_write_output, this,
            asio::placeholders::error));
    }
    else
    {
      close();
    }
  }

  void handle_write_output(const asio::error_code& error)
  {
    if (!error)
    {
      // Read the fixed-length header of the next message from the server.
      asio::async_read(socket_,
          asio::buffer(read_msg_.data(), chat_message::header_length),
          boost::bind(&posix_chat_client::handle_read_header, this,
            asio::placeholders::error));
    }
    else
    {
      close();
    }
  }

  void handle_read_input(const asio::error_code& error,
      std::size_t length)
  {
    if (!error)
    {
      // Write the message (minus the newline) to the server.
      write_msg_.body_length(length - 1);
      input_buffer_.sgetn(write_msg_.body(), length - 1);
      input_buffer_.consume(1); // Remove newline from input.
      write_msg_.encode_header();
      asio::async_write(socket_,
          asio::buffer(write_msg_.data(), write_msg_.length()),
          boost::bind(&posix_chat_client::handle_write, this,
            asio::placeholders::error));
    }
    else if (error == asio::error::not_found)
    {
      // Didn't get a newline. Send whatever we have.
      write_msg_.body_length(input_buffer_.size());
      input_buffer_.sgetn(write_msg_.body(), input_buffer_.size());
      write_msg_.encode_header();
      asio::async_write(socket_,
          asio::buffer(write_msg_.data(), write_msg_.length()),
          boost::bind(&posix_chat_client::handle_write, this,
            asio::placeholders::error));
    }
    else
    {
      close();
    }
  }

  void handle_write(const asio::error_code& error)
  {
    if (!error)
    {
      // Read a line of input entered by the user.
      asio::async_read_until(input_, input_buffer_, '\n',
          boost::bind(&posix_chat_client::handle_read_input, this,
            asio::placeholders::error,
            asio::placeholders::bytes_transferred));
    }
    else
    {
      close();
    }
  }

  void close()
  {
    // Cancel all outstanding asynchronous operations.
    socket_.close();
    input_.close();
    output_.close();
  }

private:
  tcp::socket socket_;
  posix::stream_descriptor input_;
  posix::stream_descriptor output_;
  chat_message read_msg_;
  chat_message write_msg_;
  asio::streambuf input_buffer_;
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 3)
    {
      std::cerr << "Usage: posix_chat_client <host> <port>\n";
      return 1;
    }

    asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::resolver::query query(argv[1], argv[2]);
    tcp::resolver::iterator iterator = resolver.resolve(query);

    posix_chat_client c(io_service, iterator);

    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}

#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
int main() {}
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
