/*
 *  Copyright (C) 2010 Collabora Ltd.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "webkitirendertheme.h"

#include "webkitclutterinclude.h"
#include "webkitdefaultrendertheme.h"

static WebKitIRenderTheme* fallbackRenderTheme = 0;

static void webkit_irender_theme_default_init(WebKitIRenderThemeInterface* iface);

G_DEFINE_INTERFACE(WebKitIRenderTheme, webkit_irender_theme, 0)

/* Default implementations. */
guint32 webkit_irender_theme_base_get_platform_color(WebKitIRenderTheme* theme,
                                                     WebKitIRenderThemePlatformColor color)
{
    ClutterColor black = {0, 0, 0, 255};
    return clutter_color_to_pixel(&black);
}

guint32 webkit_irender_theme_base_get_system_color(WebKitIRenderTheme* theme,
                                                   int systemColor)
{
    ClutterColor black = {0, 0, 0, 255};
    return clutter_color_to_pixel(&black);
}

gboolean webkit_irender_theme_base_get_widget_metrics(WebKitIRenderTheme* theme,
                                                      WebKitIRenderThemeWidgetMetrics* metrics)
{
    return FALSE;
}

gboolean webkit_irender_theme_base_get_scrollbar_metrics(WebKitIRenderTheme* theme,
                                                         WebKitIRenderThemeScrollbarMetrics* metrics)
{
    return FALSE;
}

gboolean webkit_irender_theme_base_paint_widget(WebKitIRenderTheme* theme,
                                                WebKitIRenderThemeWidgetType,
                                                WebKitIRenderThemeWidgetState*,
                                                gint flags,
                                                cairo_t* cr,
                                                cairo_rectangle_int_t* rect)
{
    return FALSE;
}

static void webkit_irender_theme_default_init(WebKitIRenderThemeInterface* iface)
{
    iface->get_platform_color = webkit_irender_theme_base_get_platform_color;
    iface->get_system_color = webkit_irender_theme_base_get_system_color;
    iface->get_widget_metrics = webkit_irender_theme_base_get_widget_metrics;
    iface->get_scrollbar_metrics = webkit_irender_theme_base_get_scrollbar_metrics;
    iface->paint_widget = webkit_irender_theme_base_paint_widget;
}

/* Default method implementations, to be used by any toolkit library. */

/* Generic functions. */
guint32 webkit_irender_theme_get_platform_color(WebKitIRenderTheme* theme,
                                                WebKitIRenderThemePlatformColor color)
{
    // FIXME: we should probably turn this into a function returning
    // boolean, and receiving an guint32 out argument.
    guint32 pixel = WEBKIT_IRENDER_THEME_GET_INTERFACE(theme)->get_platform_color(theme, color);

    if (pixel > 0)
        return pixel;

    return WEBKIT_IRENDER_THEME_GET_INTERFACE(fallbackRenderTheme)->get_platform_color(theme, color);
}

guint32 webkit_irender_theme_get_system_color(WebKitIRenderTheme* theme,
                                              int systemColor)
{
    return WEBKIT_IRENDER_THEME_GET_INTERFACE(theme)->get_system_color(theme, systemColor);
}

gboolean webkit_irender_theme_get_widget_metrics(WebKitIRenderTheme* theme,
                                                 WebKitIRenderThemeWidgetMetrics* metrics)
{
    if (theme == fallbackRenderTheme)
        return WEBKIT_IRENDER_THEME_GET_INTERFACE(theme)->get_widget_metrics(theme, metrics);

    // Pre-fill it with fallback values.
    WEBKIT_IRENDER_THEME_GET_INTERFACE(fallbackRenderTheme)->get_widget_metrics(theme, metrics);

    return  WEBKIT_IRENDER_THEME_GET_INTERFACE(theme)->get_widget_metrics(theme, metrics);
}

gboolean webkit_irender_theme_get_scrollbar_metrics(WebKitIRenderTheme* theme,
                                                    WebKitIRenderThemeScrollbarMetrics* metrics)
{
    return WEBKIT_IRENDER_THEME_GET_INTERFACE(theme)->get_scrollbar_metrics(theme, metrics);
}

gboolean webkit_irender_theme_paint_widget(WebKitIRenderTheme* theme,
                                           WebKitIRenderThemeWidgetType type,
                                           WebKitIRenderThemeWidgetState* state,
                                           gint flags,
                                           cairo_t* cr,
                                           cairo_rectangle_int_t* rect)
{
    WebKitIRenderThemeInterface *iface = WEBKIT_IRENDER_THEME_GET_INTERFACE(theme);

    // No point in falling back to the same theme.
    if (theme == fallbackRenderTheme)
        return iface->paint_widget(theme, type, state, flags, cr, rect);

    // Use the fallback directly if we do not have an implementation of this method in the theme.
    if (!iface->paint_widget)
        return WEBKIT_IRENDER_THEME_GET_INTERFACE(fallbackRenderTheme)->paint_widget(theme, type, state, flags, cr, rect);

    // Retry using the fallback, because paint_widget may be implemented partially.
    gboolean success = iface->paint_widget(theme, type, state, flags, cr, rect);
    if (!success)
        return WEBKIT_IRENDER_THEME_GET_INTERFACE(fallbackRenderTheme)->paint_widget(theme, type, state, flags, cr, rect);

    return success;
}

/* Default implementation. */
static WebKitIRenderTheme* defaultRenderTheme = 0;

WebKitIRenderTheme* webkit_irender_theme_get_default (void)
{
    if (!fallbackRenderTheme)
        fallbackRenderTheme = WEBKIT_IRENDER_THEME(webkit_default_render_theme_new());

    // Return the fallback if there is no default - this ensures that
    // we always have a theme.
    if (!defaultRenderTheme)
        return fallbackRenderTheme;

    return defaultRenderTheme;
}

void webkit_irender_theme_set_default (WebKitIRenderTheme* theme)
{
    defaultRenderTheme = theme;
}
