void on_message_load_photo (struct tgl_state *TLS, void *extra, int success, char *filename) {
  gchar *data = NULL;
  size_t len;
  GError *err = NULL;
  g_file_get_contents (filename, &data, &len, &err);
  int imgStoreId = purple_imgstore_add_with_id (g_memdup(data, (guint)len), len, NULL);
    
  char *image = format_img_full(imgStoreId);
  struct tgl_message *M = extra;
  switch (tgl_get_peer_type (M->to_id)) {
    case TGL_PEER_CHAT:
      debug ("PEER_CHAT\n");
      if (!our_msg(TLS, M)) {
        chat_add_message (TLS, M, image);
      }
      break;
      
    case TGL_PEER_USER:
      debug ("PEER_USER\n");
      if (out_msg(TLS, M)) {
        p2tgl_got_im (TLS, M->to_id, image, PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_IMAGES, M->date);
      } else {
        p2tgl_got_im (TLS, M->from_id, image, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_IMAGES, M->date);
      }
      break;
      
    case TGL_PEER_ENCR_CHAT:
      break;
      
    case TGL_PEER_GEO_CHAT:
      break;
  }
 
  g_free (image);
  telegram_conn *conn = TLS->ev_base;
  conn->updated = 1;
}
static void update_message_received (struct tgl_state *TLS, struct tgl_message *M) {
  debug ("received message\n");
  telegram_conn *conn = TLS->ev_base;
  conn->updated = 1;

  if (M->service) {
    debug ("service message, skipping...\n");
    char *text = format_service_msg (TLS, M);
    if (text) {
      switch (tgl_get_peer_type (M->to_id)) {
        case TGL_PEER_CHAT:
          chat_add_message (TLS, M, text);
          break;
          
        case TGL_PEER_USER:
          p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_SYSTEM, M->date);
          break;
      }
      g_free (text);
    }
    conn->updated = 1;
    return;
  }
  
  if ((M->flags & (FLAG_MESSAGE_EMPTY | FLAG_DELETED)) || !(M->flags & FLAG_CREATED)) {
    return;
  }
  if (!tgl_get_peer_type (M->to_id)) {
    warning ("Bad msg\n");
    return;
  }

  if (M->media.type == tgl_message_media_photo) {
    tgl_do_load_photo (TLS, &M->media.photo, on_message_load_photo, M);
    return;
  }

  if (!M->message) {
    return;
  }

  char *text = purple_markup_escape_text (M->message, strlen (M->message));
  switch (tgl_get_peer_type (M->to_id)) {
    case TGL_PEER_CHAT:
      debug ("PEER_CHAT\n");
      if (!our_msg(TLS, M)) {
        chat_add_message (TLS, M, text);
      }
      break;
      
    case TGL_PEER_USER:
      debug ("PEER_USER\n");
      
      // p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
      // :TODO: figure out how to add messages from different devices to history
      if (!our_msg(TLS, M)) {
        if (out_msg(TLS, M)) {
          p2tgl_got_im (TLS, M->to_id, text, PURPLE_MESSAGE_SEND, M->date);
        } else {
          p2tgl_got_im (TLS, M->from_id, text, PURPLE_MESSAGE_RECV, M->date);
        }
      }
      break;
      
    case TGL_PEER_ENCR_CHAT:
      break;
      
    case TGL_PEER_GEO_CHAT:
      break;
  }
  
  g_free (text);
}
static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
  connection_data *conn = TLS->ev_base;
  struct tgl_message *M = C->msg;
  char *text = NULL;
  int flags = 0;
  
  // Filter message updates and deletes, are not created and
  // all messages in general that were already displayed, or shouldn't be displayed
  if ((M->flags & (FLAG_MESSAGE_EMPTY | FLAG_DELETED)) ||
      !(M->flags & FLAG_CREATED) ||
      !M->message ||
      our_msg (TLS, M) ||
      !tgl_get_peer_type (M->to_id)) {
    return;
  }
  
  
  if (M->service) {
    text = format_service_msg (TLS, M);
    flags |= PURPLE_MESSAGE_SYSTEM;
  }
  else if (M->media.type == tgl_message_media_document) {
    char *who = p2tgl_strdup_id (M->from_id);
    if (! out_msg(TLS, M)) {
      tgprpl_recv_file (conn->gc, who, &M->media.document);
    }
    g_free (who);
    return;
  }
  else if (M->media.type == tgl_message_media_document_encr) {
    char *who = p2tgl_strdup_id (M->from_id);
    if (! out_msg(TLS, M)) {
      tgprpl_recv_encr_file (conn->gc, who, &M->media.encr_document);
    }
    g_free (who);
  }
  else if (M->media.type == tgl_message_media_photo) {
    char *filename = C->data;
    int imgStoreId = p2tgl_imgstore_add_with_id (filename);
    if (imgStoreId <= 0) {
      failure ("Cannot display picture message, adding to imgstore failed.");
      return;
    }
    used_images_add (conn, imgStoreId);
    text = format_img_full (imgStoreId);
    flags |= PURPLE_MESSAGE_IMAGES;
  }
  else {
    text = format_message (M);
    flags |= PURPLE_MESSAGE_RECV;
  }
  
  
  if (! text || ! *text) {
    warning ("No text to display");
    return;
  }
  switch (tgl_get_peer_type (M->to_id)) {
    case TGL_PEER_CHAT: {
      if (chat_show (conn->gc, tgl_get_peer_id (M->to_id))) {
        p2tgl_got_chat_in (TLS, M->to_id, M->from_id, text, flags, M->date);
      }
      pending_reads_add (conn->pending_reads, M->to_id);
      break;
    }
    case TGL_PEER_ENCR_CHAT: {
      p2tgl_got_im (TLS, M->to_id, text, flags, M->date);
      pending_reads_add (conn->pending_reads, M->to_id);
      break;
    }
    case TGL_PEER_USER: {
      if (out_msg (TLS, M)) {
        flags |= PURPLE_MESSAGE_SEND;
        flags &= ~PURPLE_MESSAGE_RECV;
        p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date);
      } else {
        p2tgl_got_im (TLS, M->from_id, text, flags, M->date);
        pending_reads_add (conn->pending_reads, M->from_id);
      }
      break;
    }
  }
  
  
  if (p2tgl_status_is_present (purple_account_get_active_status (conn->pa))) {
    pending_reads_send_all (conn->pending_reads, conn->TLS);
  }

  
  g_free (text);
}