/*
 * Copyright (c) 2002 Sasha Vasko <sasha at aftercode dot net>
 * Copyright (c) 1999 Ethan Fischer <allanon@crystaltokyo.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#define LOCAL_DEBUG

#include "../configure.h"
#include "asapp.h"
#include "screen.h"
#include "mystyle.h"
#include "mystyle_property.h"
#include "wmprops.h"

void
mystyle_list_set_property (ASWMProps *wmprops, ASHashTable *list )
{
    CARD32 *prop;
	int           i, nelements;
    ASHashIterator iterator ;

	nelements = 0;
    if( !start_hash_iteration( list, &iterator ) ) return ;
	do
	{
        nelements += 9 + 7 + ((MyStyle*)curr_hash_data(&iterator))->gradient.npoints * 4;
    }while( next_hash_item(&iterator));

	prop = safemalloc (sizeof (CARD32) * nelements);

	i = 0;
    start_hash_iteration( list, &iterator );
	do
	{
        MyStyle *style = (MyStyle*)curr_hash_data(&iterator);
/*    show_warning( "style \"%s\" set_flags = %X", style->name, style->set_flags );
 */
		prop[i++] = style->set_flags;
		prop[i++] = XInternAtom (dpy, style->name, False);
		prop[i++] = style->text_style;
		prop[i++] = XInternAtom (dpy, style->font.name, False);
		prop[i++] = style->colors.fore;
		prop[i++] = style->colors.back;
		prop[i++] = style->relief.fore;
		prop[i++] = style->relief.back;
		prop[i++] = style->texture_type;
		prop[i++] = style->max_colors;
		if( style->back_icon.pix == None ) 
			make_icon_pixmaps( &(style->back_icon), False );
		prop[i++] = style->back_icon.pix;
		prop[i++] = style->back_icon.mask;
		prop[i++] = style->tint;
		prop[i++] = style->back_icon.alpha;
		prop[i++] = 0;						   /* unused/reserved */
		prop[i++] = style->gradient.npoints;
		{
			int           k;

			for (k = 0; k < style->gradient.npoints; k++)
			{
				prop[i++] = style->gradient.color[k];
				prop[i++] = style->gradient.color[k];	/* for compatibility with older version */
				prop[i++] = style->gradient.color[k];	/* for compatibility with older version */
                LOCAL_DEBUG_OUT ("gradient color at offset %f is %lX", style->gradient.offset[k],
								 style->gradient.color[k]);
				prop[i++] = style->gradient.offset[k] * 0x1000000;
			}
		}
    }while( next_hash_item(&iterator));
	/* set the property version to 1.2 */
    set_as_style (wmprops, nelements *  sizeof (CARD32), (1 << 8) + 2, prop );
    free (prop);
}

void
mystyle_set_property (ASWMProps *wmprops)
{
    mystyle_list_set_property (wmprops,ASDefaultScr->Look.styles_list);
}


void
mystyle_get_property (ASWMProps *wmprops)
{
	CARD32 *prop;
	size_t        i, n;
	CARD32 version;

    if ( (prop = wmprops->as_styles_data) == NULL )
		return;
	/* do we know how to handle this version? */
    version = wmprops->as_styles_version ;
    /* do we know how to handle this version? */
	if (version != (1 << 8) + 2)
	{
        show_error("style property has unknown version %d.%d", (int)version >> 8, (int)version & 0xff);
		return;
	}

    n = wmprops->as_styles_size/sizeof (CARD32);
	for (i = 0; i < n;)
	{
		MyStyle      *style;
		char         *name;
		CARD32 flags = prop[i + 0];
		Pixmap back_pix, back_mask, back_alpha ;

		name = XGetAtomName (dpy, prop[i + 1]);
		if ((style = mystyle_find (name)) == NULL)
			style = mystyle_new_with_name (name);
		XFree (name);

		/* free up any resources that are already in use */
		if (style->user_flags & F_FONT)
            unload_font (&style->font);
		if (style->user_flags & F_BACKGRADIENT)
		{
			free (style->gradient.color);
			free (style->gradient.offset);
		}
        if (style->back_icon.image)
        {
            safe_asimage_destroy (style->back_icon.image);
            style->back_icon.image = NULL ;
        }

		style->user_flags = 0;
		style->inherit_flags = flags;
		style->text_style = prop[i + 2];

		if (style->inherit_flags & F_FONT)
		{
#ifdef MODULE_REUSE_LOADED_FONT
			XFontStruct  *font = XQueryFont (dpy, prop[i + 3]);

			style->font.name = NULL;
			style->font.font = font;
			if (font != NULL)
			{
				style->font.width = font->max_bounds.rbearing + font->min_bounds.lbearing;
				style->font.height = font->ascent + font->descent;
				style->font.y = font->ascent;
			}
#else
			name = XGetAtomName (dpy, prop[i + 3]);
			load_font (name, &style->font);
			XFree (name);
            style->user_flags |= F_FONT;
            style->inherit_flags &= ~F_FONT;
#endif
		}
		style->colors.fore = prop[i + 4];
		style->colors.back = prop[i + 5];
        LOCAL_DEBUG_OUT( "style(%p:\"%s\")->colors(#%lX,#%lX)->flags(0x%lX)->inherit_flags(0x%X)", style, style->name, style->colors.fore, style->colors.back, flags, style->inherit_flags );
		style->relief.fore = prop[i + 6];
		style->relief.back = prop[i + 7];
		style->texture_type = prop[i + 8];
		style->max_colors = prop[i + 9];
		back_pix = prop[i + 10];
		back_mask = prop[i + 11];
		style->tint = prop[i + 12];
		back_alpha = prop[i + 13];
        set_flags(style->user_flags, F_EXTERNAL_BACKPIX|F_EXTERNAL_BACKMASK);
		/* unused/reserved : */
/*    style->tint = prop[i + 14];
 */
		style->gradient.npoints = prop[i + 15];
/*	  show_warning( "checking if gradient data in style \"%s\": (set flags are : 0x%X)", style->name, style->inherit_flags);
 */
		if (style->gradient.npoints > 0 )
		{
			size_t        k;

			style->gradient.type = mystyle_translate_grad_type (style->texture_type);
			style->gradient.color = NEW_ARRAY (ARGB32, style->gradient.npoints);
			style->gradient.offset = NEW_ARRAY (double, style->gradient.npoints);

			for (k = 0; k < style->gradient.npoints; k++)
 			{
				style->gradient.color[k] = prop[i + 16 + k * 4 + 0];
				/*
				   style->gradient.color[k].green = prop[i + 16 + k * 4 + 1];
				   style->gradient.color[k].blue = prop[i + 16 + k * 4 + 2];
				 */
				style->gradient.offset[k] = (double)prop[i + 16 + k * 4 + 3] / 0x1000000;
                LOCAL_DEBUG_OUT ("gradient color at offset %f is %lX", style->gradient.offset[k],
								 style->gradient.color[k]);
			}
			style->user_flags |= F_BACKGRADIENT;
			style->inherit_flags &= ~F_BACKGRADIENT;
		}
		/* if there's a backpixmap, make sure it's valid and get its geometry */
		if (back_pix != None)
		{
 			icon_from_pixmaps( &(style->back_icon), back_pix, back_mask, back_alpha );
			if( style->back_icon.image != NULL ) 
				clear_flags (style->inherit_flags, F_BACKPIXMAP|F_BACKTRANSPIXMAP);
		}

		if (style->back_icon.pix == None && 
			style->texture_type != TEXTURE_TRANSPARENT && 
			style->texture_type != TEXTURE_TRANSPARENT_TWOWAY)
		{
			if (style->inherit_flags & F_BACKPIXMAP)
			{
				style->texture_type = 0;
				style->back_icon.mask = None;
				style->inherit_flags &= ~(F_BACKPIXMAP | F_BACKTRANSPIXMAP);
			} else if (style->inherit_flags & F_BACKTRANSPIXMAP)
			{
				fprintf (stderr, "Transpixmap requested, but no pixmap detected for style '%s'\n", style->name);
				fprintf (stderr, "This is a bug, please report it!\n");
				style->inherit_flags &= ~F_BACKTRANSPIXMAP;
			}
		}

		i += 9 + 7 + style->gradient.npoints * 4;
		LOCAL_DEBUG_OUT( "user_flags = 0x%X, inherit_flags = 0x%X", style->user_flags, style->inherit_flags );
		style->set_flags = style->user_flags | style->inherit_flags;
	}

	/* force update of global gcs */
    mystyle_fix_styles ();
}

void 
mystyle_handle_property_event( XEvent *event )
{	 
	handle_wmprop_event (ASDefaultScr->wmprops, event);
	mystyle_list_destroy_all(&(ASDefaultScr->Look.styles_list));
	mystyle_get_property(ASDefaultScr->wmprops);
}

