/* This is directly taken from gtk+/demos/gtk-demo/foreigndrawing.c
 * Gtk+ is license under LGPLv2+
 */

#include <string.h>

#include "ut_assert.h"

#include "xap_GtkStyle.h"

static void
append_element (GtkWidgetPath *path,
                const char    *selector)
{
#if 0
  static const struct {
    const char    *name;
    GtkStateFlags  state_flag;
  } pseudo_classes[] = {
    { "active",        GTK_STATE_FLAG_ACTIVE },
    { "hover",         GTK_STATE_FLAG_PRELIGHT },
    { "selected",      GTK_STATE_FLAG_SELECTED },
    { "disabled",      GTK_STATE_FLAG_INSENSITIVE },
    { "indeterminate", GTK_STATE_FLAG_INCONSISTENT },
    { "focus",         GTK_STATE_FLAG_FOCUSED },
    { "backdrop",      GTK_STATE_FLAG_BACKDROP },
    { "dir(ltr)",      GTK_STATE_FLAG_DIR_LTR },
    { "dir(rtl)",      GTK_STATE_FLAG_DIR_RTL },
    { "link",          GTK_STATE_FLAG_LINK },
    { "visited",       GTK_STATE_FLAG_VISITED },
    { "checked",       GTK_STATE_FLAG_CHECKED },
    { "drop(active)",  GTK_STATE_FLAG_DROP_ACTIVE }
  };
  guint i;
#endif
  const char *next;
  char *name;
  char type;

  next = strpbrk (selector, "#.:");
  if (next == NULL)
    next = selector + strlen (selector);

  name = g_strndup (selector, next - selector);
  if (g_ascii_isupper (selector[0]))
    {
      GType gtype;
      gtype = g_type_from_name (name);
      if (gtype == G_TYPE_INVALID)
        {
          g_critical ("Unknown type name `%s'", name);
          g_free (name);
          return;
        }
      gtk_widget_path_append_type (path, gtype);
    }
  else
    {
#if 0
      /* Omit type, we're using name */
      gtk_widget_path_append_type (path, G_TYPE_NONE);
      gtk_widget_path_iter_set_object_name (path, -1, name);
#else
      UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
#endif
    }
  g_free (name);

  while (*next != '\0')
    {
      type = *next;
      selector = next + 1;
      next = strpbrk (selector, "#.:");
      if (next == NULL)
        next = selector + strlen (selector);
      name = g_strndup (selector, next - selector);

      switch (type)
        {
        case '#':
          gtk_widget_path_iter_set_name (path, -1, name);
          break;

        case '.':
          gtk_widget_path_iter_add_class (path, -1, name);
          break;

        case ':':
#if 0
          for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
            {
              if (g_str_equal (pseudo_classes[i].name, name))
                {
                  gtk_widget_path_iter_set_state (
                    path,
                    -1,
                    (GtkStateFlags)(gtk_widget_path_iter_get_state (path, -1)
                                    | pseudo_classes[i].state_flag));
                  break;
                }
            }
          if (i == G_N_ELEMENTS (pseudo_classes))
            g_critical ("Unknown pseudo-class :%s", name);
#else
          // you reached it, check what you passed to XAP_GtkStyle_get_style()
          // this require a version of Gtk that is too recent.
          // XXX eventually fix when we bump the requirements.
          UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
#endif
          break;

        default:
          g_assert_not_reached ();
          break;
        }

      g_free (name);
    }
}

static GtkStyleContext *
create_context_for_path (GtkWidgetPath   *path,
                         GtkStyleContext * /*parent*/)
{
  GtkStyleContext *context;

  context = gtk_style_context_new ();
  gtk_style_context_set_path (context, path);
#if 0 // Gtk 3.4 minimum - no parent set anyway
  gtk_style_context_set_parent (context, parent);
#endif
  /* Unfortunately, we have to explicitly set the state again here
   * for it to take effect
   */
#if 0 // we haven't set a state anyway.
  gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
#endif
  gtk_widget_path_free (path);

  return context;
}

GtkStyleContext *
XAP_GtkStyle_get_style (GtkStyleContext *parent,
                        const char      *selector)
{
  GtkWidgetPath *path;

  if (parent)
    path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
  else
    path = gtk_widget_path_new ();

  append_element (path, selector);

  return create_context_for_path (path, parent);
}

