camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
{
	gboolean needs_foreign = FALSE, has_foreign = FALSE;
	gboolean needs_public = FALSE, has_public = FALSE;
	CamelFolderInfo *fi;
	GSList *folders, *iter;
	GHashTable *children_count;
	GHashTableIter tab_iter;
	gpointer key, value;

	g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));

	folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL);
	if (!folders)
		return;

	children_count = g_hash_table_new (g_str_hash, g_str_equal);

	for (iter = folders; iter; iter = iter->next) {
		const gchar *fid = iter->data;
		GError *error = NULL;

		if (!fid)
			continue;

		if (g_str_has_prefix (fid, "ForeignMailbox::") &&
		    !g_hash_table_contains (children_count, fid))
			g_hash_table_insert (children_count, (gpointer) fid, GINT_TO_POINTER (0));

		if (g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID) &&
		    !g_hash_table_contains (children_count, fid))
			g_hash_table_insert (children_count, (gpointer) fid, GINT_TO_POINTER (0));

		if (!has_foreign && g_str_equal (fid, EWS_FOREIGN_FOLDER_ROOT_ID))
			has_foreign = TRUE;
		else if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, &error) && !error) {
			gchar *pfid;

			needs_foreign = TRUE;

			pfid = camel_ews_store_summary_get_parent_folder_id (ews_store->summary, fid, NULL);
			if (pfid && g_str_has_prefix (pfid, "ForeignMailbox::")) {
				gint count = GPOINTER_TO_INT (g_hash_table_lookup (children_count, pfid));

				g_hash_table_insert (children_count, (gpointer) pfid, GINT_TO_POINTER (count + 1));
			}
		}

		g_clear_error (&error);

		if (!has_public && g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID))
			has_public = TRUE;
		else if (camel_ews_store_summary_get_public (ews_store->summary, fid, &error) && !error) {
			EEwsFolderType ftype;
			gchar *pfid;

			ftype = camel_ews_store_summary_get_folder_type (ews_store->summary, fid, &error);
			if (ftype == E_EWS_FOLDER_TYPE_MAILBOX && !error) {
				guint64 fflags;

				fflags = camel_ews_store_summary_get_folder_flags (ews_store->summary, fid, &error);
				if ((fflags & CAMEL_FOLDER_SUBSCRIBED) != 0 && !error) {
					needs_public = TRUE;

					pfid = camel_ews_store_summary_get_parent_folder_id (ews_store->summary, fid, NULL);
					if (pfid && g_str_equal (pfid, EWS_PUBLIC_FOLDER_ROOT_ID)) {
						gint count = GPOINTER_TO_INT (g_hash_table_lookup (children_count, pfid));

						g_hash_table_insert (children_count, (gpointer) pfid, GINT_TO_POINTER (count + 1));
					}
				}
			}
		}

		g_clear_error (&error);
	}

	g_hash_table_iter_init (&tab_iter, children_count);
	while (g_hash_table_iter_next (&tab_iter, &key, &value)) {
		gint count = GPOINTER_TO_INT (value);

		if (!count) {
			CamelFolderInfo *fi;

			if (has_foreign && g_str_equal (key, EWS_FOREIGN_FOLDER_ROOT_ID))
				has_foreign = FALSE;

			if (has_public && g_str_equal (key, EWS_PUBLIC_FOLDER_ROOT_ID))
				has_public = FALSE;

			fi = camel_ews_utils_build_folder_info (ews_store, key);
			camel_ews_store_summary_remove_folder (ews_store->summary, key, NULL);

			camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
			camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
			camel_folder_info_free (fi);
		}
	}

	g_hash_table_destroy (children_count);

	if (needs_foreign && !has_foreign) {
		gchar *use_name = NULL;
		gchar *tmp_fid;
		gint counter = 0;

		tmp_fid = camel_ews_store_summary_get_folder_id_from_name (
			ews_store->summary, EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME);
		while (tmp_fid) {
			counter++;

			g_free (tmp_fid);
			g_free (use_name);

			use_name = g_strdup_printf (
				/* Translators: This composes a "Foreign Folders" folder name for case when
				 * user has such in his store already. The %s is replaced with "Foreign Folders",
				 * the %d with counter, thus it composes name like "Foreign Folders_1"
				 */
				C_("ForeignFolders", "%s_%d"),
				EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME, counter);

			tmp_fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, use_name);
		}

		camel_ews_store_summary_new_folder (
			ews_store->summary,
			EWS_FOREIGN_FOLDER_ROOT_ID, NULL, NULL,
			use_name ? use_name : EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME,
			E_EWS_FOLDER_TYPE_MAILBOX,
			CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
			0, FALSE, FALSE);

		g_free (use_name);

		fi = camel_ews_utils_build_folder_info (ews_store, EWS_FOREIGN_FOLDER_ROOT_ID);
		camel_store_folder_created (CAMEL_STORE (ews_store), fi);
		camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
		camel_folder_info_free (fi);
	} else if (has_foreign && !needs_foreign) {
		CamelFolderInfo *fi;

		fi = camel_ews_utils_build_folder_info (ews_store, EWS_FOREIGN_FOLDER_ROOT_ID);
		camel_ews_store_summary_remove_folder (ews_store->summary, EWS_FOREIGN_FOLDER_ROOT_ID, NULL);

		camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
		camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
		camel_folder_info_free (fi);
	}

	if (needs_public && !has_public) {
		gchar *use_name;

		use_name = ews_store_get_public_folders_name (ews_store);

		camel_ews_store_summary_new_folder (
			ews_store->summary,
			EWS_PUBLIC_FOLDER_ROOT_ID, NULL, NULL,
			use_name ? use_name : EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME,
			E_EWS_FOLDER_TYPE_MAILBOX,
			CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
			0, FALSE, FALSE);

		g_free (use_name);

		fi = camel_ews_utils_build_folder_info (ews_store, EWS_PUBLIC_FOLDER_ROOT_ID);
		camel_store_folder_created (CAMEL_STORE (ews_store), fi);
		camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
		camel_folder_info_free (fi);
	} else if (has_public && !needs_public) {
		CamelFolderInfo *fi;

		fi = camel_ews_utils_build_folder_info (ews_store, EWS_PUBLIC_FOLDER_ROOT_ID);
		camel_ews_store_summary_remove_folder (ews_store->summary, EWS_PUBLIC_FOLDER_ROOT_ID, NULL);

		camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
		camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
		camel_folder_info_free (fi);
	}

	camel_ews_store_summary_rebuild_hashes (ews_store->summary);
	camel_ews_store_summary_save (ews_store->summary, NULL);

	g_slist_free_full (folders, g_free);
}