/* Swfdec Mozilla Plugin
 * Copyright (C) 2006 Benjamin Otte <otte@gnome.org>
 *
 * 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
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <unistd.h>
#include <npapi.h>
#include <npupp.h>

#include "directfb.h"
#include "plugin.h"
#include "plugin_fb.h"
#include "flash_event.h"

/*** Plugin code ***/

void
plugin_fb_convert_key(int plugin_key, int *swfdec_key, int *popup_menu)
{
	printf("plugin_key = %d\n", plugin_key);
	switch (plugin_key)
	{
	case 61442:
	case DIKI_UP:
		*swfdec_key = 1;
		break;
	case 61443:
	case DIKI_DOWN:
		*swfdec_key = 2;
		break;
	case 61440:
	case DIKI_LEFT:
		*swfdec_key = 3;
		break;
	case 61441:
	case DIKI_RIGHT:
		*swfdec_key = 4;
		break;
	case 13:
	case DIKI_ENTER:
		*swfdec_key = 5;
		break;
	case 61471: /* POP-UP MENU */
	case 62976: /* POP-UP MENU */
		*popup_menu = 1;
	default:
		*swfdec_key = 0;
		break;
	}
}

void
plugin_fb_handle_event (void *p, void *event)
{
	DFBEvent* _event = (DFBEvent*)event;
	int p1 = 0, p2 = 0, p3 = 0;
	int popup_menu = 0;
	static int move_mouse = 0;
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	
	printf("handle_event!\n");

	switch(_event->clazz)
	{
	case DFEC_WINDOW:
	    {
	      DFBWindowEvent *winEvent = (DFBWindowEvent*)_event;
	      if (winEvent->type == DWET_KEYDOWN)
            p3 = 1;
	      else 
            p3 = 0;
          plugin_fb_convert_key(winEvent->key_id, &p1, &popup_menu);
	    }
	    break;
	case DFEC_INPUT:
	    {   
	      DFBInputEvent *inputEvent = (DFBInputEvent*)_event;
	      if (inputEvent->type == DIET_KEYPRESS)
            p3 = 1;
	      else
            p3 = 0;
          plugin_fb_convert_key(inputEvent->key_id, &p1, &popup_menu);
	    }
	    break;
	default:
	    break;
	}
	if (p3 && pdata->eventfd != -1)
	{
		if (!popup_menu)
		{
			FlashEvent evt;
			evt.type = EVENTTYPE_KEY;
			evt.len = sizeof(FlashEvent);
			evt.key.p1 = p1;
			evt.key.p2 = p2;
			evt.key.p3 = 1;
			write(pdata->eventfd, (char *)&evt, evt.len);
			evt.key.p3 = 0;
			write(pdata->eventfd, (char *)&evt, evt.len);
		}
		else
		{
			move_mouse = !move_mouse;
			FlashEvent evt;
			evt.type = EVENTTYPE_MOUSE;
			evt.len = sizeof(FlashEvent);
			evt.mouse.p1 = move_mouse ? 1 : 2;
			evt.mouse.p2 = move_mouse ? 1 : 2;
			evt.mouse.p3 = 0;
			write(pdata->eventfd, (char *)&evt, evt.len);
		}
	}
}

void
plugin_fb_setup_windowed (void *p, void *window,
    int x, int y, int width, int height)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	if (pdata->window != window) 
		pdata->window = window;
	FlashEvent evt;
	evt.type = EVENTTYPE_RESIZE;
	evt.len = sizeof(FlashEvent);
	evt.resize.x = x;
	evt.resize.y = y;
	evt.resize.w = width;
	evt.resize.h = height;
	write(pdata->eventfd, (char *)&evt, evt.len);
}

void
plugin_fb_teardown (void *p)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	pdata->window = NULL;
}

void
plugin_fb_focus(void *p)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	FlashEvent evt;
	evt.type = EVENTTYPE_FOCUS;
	evt.len = sizeof(FlashEvent);
	write(pdata->eventfd, (char *)&evt, evt.len);
}

void
plugin_fb_blur(void *p)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	FlashEvent evt;
	evt.type = EVENTTYPE_BLUR;
	evt.len = sizeof(FlashEvent);
	write(pdata->eventfd, (char *)&evt, evt.len);
}

void 
plugin_fb_seturl(void *p, char * url)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	if (url == NULL)
		return;
	char *buf = (char *)malloc(sizeof(FlashEvent) + strlen(url) + 1);
	if (buf == NULL)
		return;
	FlashEvent *evt = (FlashEvent *)buf;
	evt->type = EVENTTYPE_SETURL;
	evt->len = sizeof(FlashEvent) + strlen(url) + 1;
	evt->seturl.len = strlen(url) + 1;
	strcpy(evt->seturl.data, url);
    evt->seturl.data[evt->seturl.len - 1] = '\0';
	write(pdata->eventfd, (char *)evt, evt->len);
	free(buf);
}

void
plugin_fb_exit(void *p)
{
	PLUGIN_PDATA * pdata = (PLUGIN_PDATA *)p;
	FlashEvent evt;
	evt.type = EVENTTYPE_EXIT;
	evt.len = sizeof(FlashEvent);
	write(pdata->eventfd, (char *)&evt, evt.len);
}

int
plugin_fb_has_method(void *p,
	NPIdentifier name)
{
	PLUGIN_PDATA *pdata = (PLUGIN_PDATA *)p;
	int i = 0;
	for (i = 0; i < pdata->invoke_cnt; i++)
	{
  		if (name == pdata->invoke_name[i])
			return 1;
	}
	return 0;
}

static char g_EventBuffer[MAX_FLASH_EVENT_SIZE];

int
plugin_fb_invoke(void *p,
	NPUTF8 *utf8,
	const NPVariant *args,
	uint32_t argCount,
	NPVariant *result)
{
	PLUGIN_PDATA *pdata = (PLUGIN_PDATA *)p;
	FlashEvent * event=(FlashEvent *)g_EventBuffer;
 	FlashEventCallItem * item = NULL;
	char *pos = NULL;
	uint32_t i = 0;
	int ret = 0;
    int nfds = 0;
    fd_set readset;
    struct timeval tv;

	event->type=EVENTTYPE_CALL;
	event->call.count=argCount+1;
	item = &event->call.item[0];
	item->type = 3;
	item->len=strlen(utf8)+1;
	memcpy(item->data, utf8, item->len);
	item->data[item->len-1]=0;
	pos = &item->data[item->len];
	for (i = 0; i < argCount; i++)
	{
		item = (FlashEventCallItem *)pos;
		if(args[i].type==NPVariantType_Int32)
		{
    		item->type=0;
    		item->len=sizeof(int);
    		*(int *)item->data=(int)args[i].value.intValue;
		}
		else if(args[i].type==NPVariantType_Bool)
		{
    		item->type=1;
    		item->len=1;
    		item->data[0]=args[i].value.boolValue?1:0;
		}
		else if(args[i].type==NPVariantType_Double)
		{
    		item->type=2;
    		item->len=sizeof(double);
    		*(double *)item->data=args[i].value.doubleValue;
		}
		else if(args[i].type==NPVariantType_String)
		{
    		item->type=3;
    		item->len=args[i].value.stringValue.utf8length+1;
    		memcpy(item->data,args[i].value.stringValue.utf8characters, item->len);
    		item->data[item->len-1]=0;
		}
		pos = &item->data[item->len];
	}
	event->len = pos - g_EventBuffer;
	ret = write(pdata->eventfd, g_EventBuffer, event->len);
	/* wait return */
    tv.tv_sec = 10;
    tv.tv_usec = 0;
    FD_ZERO(&readset);
    FD_SET(pdata->evretfd, &readset);
    nfds = select(pdata->evretfd + 1, &readset, NULL, NULL, &tv);
    if (nfds == -1)
    {
    }
    else if (FD_ISSET(pdata->evretfd, &readset))
    {
    	char ret_buf[64];
        int ret_size=read(pdata->evretfd,ret_buf,64);
        printf("Call AS End ret size %d\n",ret_size);
    }
    else
    {
    }
	/* ToDo: Return the right value. */
	if(result)
	{
    	result->type = NPVariantType_Int32;
    	result->value.intValue = 0;
	}
	return 1;
}

