int main(int argc, char** argv)
{
  // Sleep a bit before starting.
  std::this_thread::sleep_for(std::chrono::seconds(1));

  client::Client c;
  client::State state;

  using namespace std::literals;
  using namespace pong::literals;

  using client::Launch_State;

  // Start the engine with 1000x1000 window.
  using client::make_params;

  auto const& params = make_params(pong::Vec<int>(1000, 1000), "Pong Plus More"s);
  c.post_request({1_id, "Core.Start", params},
  [&state, &c](pong::Response const& res)
  {
    // If we have an error on our hands...
    if(pong::is_error_response(res))
    {
      pong::Error_Response err = pong::get_error_response(res);
      client::log_message(c, pong::Log_Severity::Error,
                          err.msg + " (Error code: " +
                          std::to_string(err.code) + ")");
      state.run_state = Launch_State::Error;
    }
    else
    {
      // Successful start!
      state.run_state = Launch_State::Running;
    }
  });

  {
    pong::Timer<> run_timer;
    while(state.run_state == Launch_State::Not_Running)
    {
      if(run_timer.has_been(std::chrono::seconds(5))) break;
      c.step();
    }

    switch(state.run_state)
    {
      case Launch_State::Not_Running:
      {
        client::log_message(c, pong::Log_Severity::Error,
                            "Timed out waiting for starting confirmation.");
        return EXIT_FAILURE;
      }
      case Launch_State::Error:
      {
        // Failed to launch for some reason. Already being logged in the
        // request callback.
        return EXIT_FAILURE;
      }
      // If the engine started successfully let control continue.
      case Launch_State::Running:
      {
        // Log the success!
        client::log_message(c, pong::Log_Severity::Error,
                            "Successful engine start");
      }
    }
  }

  // We are running now.

  // Wait for 2 seconds before exiting.
  std::this_thread::sleep_for(std::chrono::seconds(2));

  // Exit/close the engine/window.
  c.post_request({boost::none_t{}, "Core.Exit"});
}