/*
 * Test case to https://bugzilla.gnome.org/show_bug.cgi?id=774726
 *
 * GtkTreeView dnd: gtk_drag_finish remove row when reorder sinse 3.20
 *
 * Compile with: gcc `pkg-config --cflags gtk+-3.0` -o test-case test-case.c `pkg-config --libs gtk+-3.0`
 */

#include <gtk/gtk.h>

typedef enum {
	TARGET_REF_LIBRARY,
	TARGET_URI_LIST,
	TARGET_PLAIN_TEXT
} PraghaDndTarget;

static const GtkTargetEntry pentries[] = {
	{"REF_LIBRARY", GTK_TARGET_SAME_APP, TARGET_REF_LIBRARY},
	{"text/uri-list", GTK_TARGET_OTHER_APP, TARGET_URI_LIST},
	{"text/plain", GTK_TARGET_OTHER_APP, TARGET_PLAIN_TEXT}
};

enum playlist_columns {
	P_TEXT,
	N_P_COLUMNS
};

void
dnd_current_playlist_reorder(GtkTreeModel *model,
			     GtkTreeIter *dest_iter,
			     GtkTreeViewDropPosition pos,
			     GtkWidget *view)
{
	GtkTreeRowReference *ref;
	GtkTreePath *path = NULL;
	GtkTreeSelection *selection;
	GtkTreeIter iter;
	GList *list = NULL, *l;

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
	list = gtk_tree_selection_get_selected_rows(selection, NULL);

	/* No selections */
	if (!list)
		goto exit;

	/* Store references to the selected paths */
	l = list;
	while(l) {
		path = l->data;
		ref = gtk_tree_row_reference_new(model, path);
		l->data = ref;
		gtk_tree_path_free(path);
		l = l->next;
	}

	/* Move to new position */

	for (l=list; l != NULL; l = l->next) {
		ref = l->data;
		path = gtk_tree_row_reference_get_path(ref);
		gtk_tree_model_get_iter(model, &iter, path);

		if (pos == GTK_TREE_VIEW_DROP_BEFORE)
			gtk_list_store_move_before(GTK_LIST_STORE(model), &iter, dest_iter);
		else if (pos == GTK_TREE_VIEW_DROP_AFTER)
			gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, dest_iter);

		gtk_tree_path_free(path);
		gtk_tree_row_reference_free(ref);
	}

exit:
	g_list_free(list);
}

/* Callback for DnD signal 'drag-data-received' */

static void
dnd_current_playlist_received(GtkWidget *playlist_view,
			     GdkDragContext *context,
			     gint x,
			     gint y,
			     GtkSelectionData *data,
			     PraghaDndTarget info,
			     guint time,
			     GtkWidget *view)
{
	GtkTreeModel *model;
	GtkTreePath *dest_path = NULL;
	GtkTreeIter dest_iter;
	GtkTreeViewDropPosition pos = 0;
	gboolean is_row;
	GdkRectangle vrect, crect;
	gdouble row_align;
	GList *list = NULL;

	model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));

	is_row = gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(view),
						x, y,
						&dest_path,
						&pos);

	gtk_tree_view_get_visible_rect(GTK_TREE_VIEW(playlist_view), &vrect);
	gtk_tree_view_get_cell_area(GTK_TREE_VIEW(playlist_view), dest_path, NULL, &crect);

	row_align = (gdouble)crect.y / (gdouble)vrect.height;

	switch(pos) {
		case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
			pos = GTK_TREE_VIEW_DROP_BEFORE;
			break;
		case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
			pos = GTK_TREE_VIEW_DROP_AFTER;
			break;
		default:
			break;
	}

	if (is_row)
		gtk_tree_model_get_iter (model, &dest_iter, dest_path);

	/* Reorder within current playlist */

	if (gtk_drag_get_source_widget(context) == view) {
		g_message("Reorder music list");
		dnd_current_playlist_reorder(model, &dest_iter, pos, view);
		goto exit;
	}

	/* Get new tracks to append on playlist */

	switch(info) {
	case TARGET_REF_LIBRARY:
		g_message("Get music list from library pane");
		//list = pragha_dnd_library_get_mobj_list (data, cplaylist->cdbase);
		break;
	case TARGET_URI_LIST:
		g_message("Get music list from file browser");
		//list = pragha_dnd_uri_list_get_mobj_list (data);
		break;
	case TARGET_PLAIN_TEXT:
		g_message("Get music list from file browser");
		//list = pragha_dnd_plain_text_get_mobj_list (data);
		break;
	default:
		g_warning("Unknown DND type");
		break;
	}

	/* Insert mobj list to current playlist. */

	if (is_row) {
		g_message("Insert new row:");
		//pragha_playlist_insert_mobj_list(cplaylist, list, pos, &dest_iter);
		gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(playlist_view), dest_path, NULL, TRUE, row_align, 0.0);
	}
	else {
		//pragha_playlist_append_mobj_list(cplaylist, list);
		g_message("append new row");
	}


	g_list_free(list);

exit:
	gtk_tree_path_free(dest_path);
	gtk_drag_finish(context, TRUE, FALSE, time);
}


static void
activate (GtkApplication* app,
          gpointer        user_data)
{
	GtkWidget *window;
	GtkWidget *view;
	GtkListStore *store;
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GtkTreeSortable *sortable;
	GtkCellRenderer *renderer;
	GtkTreeViewColumn *column;
	GtkTreeIter iter;

	/*
	 * Default gtk example.
	 */
	window = gtk_application_window_new (app);
	gtk_window_set_title (GTK_WINDOW (window), "Window");
	gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);

	/*
	 * Test case.
	 *  Simplified code of: https://github.com/pragha-music-player/pragha/blob/master/src/pragha-playlist.c
	 */
	store = gtk_list_store_new(N_P_COLUMNS, G_TYPE_STRING);
	view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));

	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new();
	gtk_cell_renderer_set_fixed_size (renderer, 1, -1);
	gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer),1);
	column = gtk_tree_view_column_new_with_attributes("Title",
	                                                  renderer,
	                                                  "text",
	                                                  P_TEXT,
	                                                  NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);

	/* Source/Dest: Current Playlist */

	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW(view),
	                                        GDK_BUTTON1_MASK,
	                                        pentries,
	                                        G_N_ELEMENTS(pentries),
	                                        GDK_ACTION_COPY | GDK_ACTION_MOVE);

	gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW(view),
	                                      pentries,
	                                      G_N_ELEMENTS(pentries),
	                                      GDK_ACTION_COPY | GDK_ACTION_MOVE);

	/* Connect signal */

	g_signal_connect (G_OBJECT(view),
	                  "drag-data-received",
	                  G_CALLBACK(dnd_current_playlist_received),
	                  view);

	/* Show all */

	gtk_container_add (GTK_CONTAINER(window), view);
	gtk_widget_show_all (window);

	/* Fill with some rows */

	model = gtk_tree_view_get_model (GTK_TREE_VIEW(view));
	for (int i = 0 ; i < 10 ; i++)
	{
		gchar *title = g_strdup_printf("Song %i", i);
		gtk_list_store_append (GTK_LIST_STORE(model), &iter);
		gtk_list_store_set (GTK_LIST_STORE(model), &iter,
		                    P_TEXT, title, -1);
		g_free(title);
	}
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}
