/**
 * inf_text_default_delete_operation_get_chunk:
 * @operation: A #InfTextDefaultDeleteOperation.
 *
 * Returns the text deleted by @operation.
 *
 * Return Value: A #InfTextChunk, owned by the operation.
 **/
InfTextChunk*
inf_text_default_delete_operation_get_chunk(
  InfTextDefaultDeleteOperation* operation)
{
  g_return_val_if_fail(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation), NULL);
  return INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation)->chunk;
}
static void
inf_text_default_delete_operation_apply(InfAdoptedOperation* operation,
                                        InfAdoptedUser* by,
                                        InfBuffer* buffer)
{
  InfTextDefaultDeleteOperationPrivate* priv;

  g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation));
  g_assert(INF_TEXT_IS_BUFFER(buffer));

  priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation);

#ifdef DELETE_OPERATION_CHECK_TEXT_MATCH
  g_assert(
    inf_text_default_delete_operation_text_match(
      INF_TEXT_DEFAULT_DELETE_OPERATION(operation),
      INF_TEXT_BUFFER(buffer)
    )
  );
#endif /* DELETE_OPERATION_CHECK_TEXT_MATCH */

  inf_text_buffer_erase_text(
    INF_TEXT_BUFFER(buffer),
    priv->position,
    inf_text_chunk_get_length(priv->chunk),
    INF_USER(by)
  );
}
static InfAdoptedOperation*
inf_text_default_delete_operation_transform(InfAdoptedOperation* operation,
                                            InfAdoptedOperation* against,
                                            InfAdoptedConcurrencyId cid)
{
  g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation));

  if(INF_TEXT_IS_INSERT_OPERATION(against))
  {
    return inf_text_delete_operation_transform_insert(
      INF_TEXT_DELETE_OPERATION(operation),
      INF_TEXT_INSERT_OPERATION(against),
      cid
    );
  }
  else if(INF_TEXT_IS_DELETE_OPERATION(against))
  {
    return inf_text_delete_operation_transform_delete(
      INF_TEXT_DELETE_OPERATION(operation),
      INF_TEXT_DELETE_OPERATION(against),
      cid
    );
  }
  else
  {
    g_assert_not_reached();
    return NULL;
  }
}
static InfAdoptedConcurrencyId
inf_text_default_delete_operation_get_concurrency_id(
  InfAdoptedOperation* operation,
  InfAdoptedOperation* against)
{
  g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation));

  return inf_text_delete_operation_get_concurrency_id(
    INF_TEXT_DELETE_OPERATION(operation),
    against
  );
}
static InfTextDeleteOperation*
inf_text_remote_delete_operation_transform_overlap(
  InfTextDeleteOperation* operation,
  InfTextDeleteOperation* other,
  guint position,
  guint begin,
  guint other_begin,
  guint length)
{
  InfTextRemoteDeleteOperationPrivate* priv;
  InfTextChunk* chunk;
  GObject* result;
  InfTextRemoteDeleteOperationPrivate* result_priv;


  /* It is actually possible that two remote delete operations are
   * transformed against each other (actually the parts of a splitted
   * remote delete operation). However, they must not overlap. */
  g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(other));

  priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation);

  chunk = inf_text_chunk_substring(
    inf_text_default_delete_operation_get_chunk(
      INF_TEXT_DEFAULT_DELETE_OPERATION(other)
    ),
    other_begin,
    length
  );

  result = g_object_new(
    INF_TEXT_TYPE_REMOTE_DELETE_OPERATION,
    "position", position,
    "length", priv->length - length,
    NULL
  );

  result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(result);

  result_priv->recon = inf_text_remote_delete_operation_recon_feed(
    priv->recon,
    begin,
    chunk
  );

  inf_text_chunk_free(chunk);

  result_priv->recon_offset = priv->recon_offset;
  return INF_TEXT_DELETE_OPERATION(result);
}