/* Note plugin implementation */
static InfSession*
infinoted_plugin_note_chat_session_new(InfIo* io,
                                       InfCommunicationManager* manager,
                                       InfSessionStatus status,
                                       InfCommunicationGroup* sync_group,
                                       InfXmlConnection* sync_connection,
                                       const gchar* path,
                                       gpointer user_data)
{
  InfChatBuffer* buffer;
  InfChatSession* session;

  buffer = inf_chat_buffer_new(256);

  session = inf_chat_session_new(
    manager,
    buffer,
    status,
    INF_COMMUNICATION_GROUP(sync_group),
    sync_connection
  );

  g_object_unref(buffer);
  return INF_SESSION(session);
}
static InfSession*
infd_note_plugin_text_session_new(InfIo* io,
                                  InfCommunicationManager* manager,
                                  InfSessionStatus status,
                                  InfCommunicationHostedGroup* sync_group,
                                  InfXmlConnection* sync_connection,
                                  gpointer user_data)
{
  InfTextSession* session;

  session = inf_text_session_new(
    manager,
    INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")),
    io,
    status,
    INF_COMMUNICATION_GROUP(sync_group),
    sync_connection
  );

  return INF_SESSION(session);
}
/**
 * inf_communication_manager_join_group:
 * @manager: A #InfCommunicationManager.
 * @group_name: The group to join.
 * @publisher_conn: A #InfXmlConnection to the publishing host.
 * @method: The communication method to use.
 *
 * Joins a communication group published by a remote host. @publisher_conn
 * needs to be a to the publishing host with status %INF_XML_CONNECTION_OPEN
 * or %INF_XML_CONNECTION_OPENING. @group_name specifies the name of the group
 * to join.
 *
 * @method specifies the communication method to use. It must match the
 * communication method the publisher has chosen for @publisher_conn's network
 * (see inf_communication_group_get_method_for_network()). The function
 * returns %NULL if @method is not supported (which means
 * inf_communication_manager_get_factory_for() for @publisher_conn's network
 * and @method returns %NULL).
 *
 * Returns: A new #InfCommunicationJoinedGroup, or %NULL. Free with
 * g_object_unref() to leave the group.
 */
InfCommunicationJoinedGroup*
inf_communication_manager_join_group(InfCommunicationManager* manager,
                                     const gchar* group_name,
                                     InfXmlConnection* publisher_conn,
                                     const gchar* method)
{
  InfCommunicationManagerPrivate* priv;
  InfCommunicationManagerJoinedKey* key;
  gchar* network;
  gchar* publisher_id;
  InfXmlConnectionStatus status;
  InfCommunicationJoinedGroup* group;

  g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL);
  g_return_val_if_fail(group_name != NULL, NULL);
  g_return_val_if_fail(INF_IS_XML_CONNECTION(publisher_conn), NULL);
  g_return_val_if_fail(method != NULL, NULL);

  priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager);

  g_object_get(
    G_OBJECT(publisher_conn),
    "network", &network,
    "remote-id", &publisher_id,
    "status", &status,
    NULL
  );

  /* TODO: Do we need to support OPENING somewhere? I don't think it's a good
   * idea to do here. When we change this remember to change docs above. */
  if(status == INF_XML_CONNECTION_CLOSING ||
     status == INF_XML_CONNECTION_CLOSED)
  {
    g_free(network);
    g_free(publisher_id);
    g_return_val_if_reached(NULL);
  }

  key = g_slice_new(InfCommunicationManagerJoinedKey);
  key->network = network;
  key->publisher_id = publisher_id;
  key->group_name = group_name;

  group = g_hash_table_lookup(priv->joined_groups, key);
  if(group != NULL)
  {
    inf_communication_manager_joined_key_free(key);
    g_return_val_if_reached(NULL);
  }

  if(!inf_communication_manager_get_factory_for(manager, network, method))
  {
    inf_communication_manager_joined_key_free(key);
    return NULL; /* ordinary failure for now */
  }

  group = g_object_new(
    INF_COMMUNICATION_TYPE_JOINED_GROUP,
    "communication-manager", manager,
    "communication-registry", priv->registry,
    "name", group_name,
    "publisher", publisher_conn,
    "method", method,
    NULL
  );

  key->group_name =
    inf_communication_group_get_name(INF_COMMUNICATION_GROUP(group));

  g_hash_table_insert(priv->joined_groups, key, group);

  g_object_weak_ref(
    G_OBJECT(group),
    inf_communication_manager_joined_group_unrefed,
    manager
  );

  return group;
}