/*----------------------------------------------------------
  PROJECT		: mldkgui

  FILE			: MLdkGUI.cpp
  VERSION		: 1.0

  CREATION		: 02.2004
  AUTHOR		: JLac
  LANGUAGE		: cpp
  AIM			: -

  HISTORIC  	: -

-----------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <pthread.h>
#include <semaphore.h>

#include <list>
#include <vector>
#include <string>

#include "typedef.h"
#include "defines.h"

using namespace std;

#include "plugin.h"
#include "osd.h"

#include "cSocketM.h"
#include "cFileInfo.h"
#include "cStreamData.h"
#include "cNetworkInfo.h"
#include "cServerInfo.h"
#include "cLstServerInfo.h"
#include "cMLDonkeyStatus.h"
#include "cItemAction.h"


#include "MLdkGUI.h"


#include "cOsdBasicDisplay.h"
#include "cOsdListReportMenu.h"
#include "cItemAction.h"
#include "cOsdBasicDisplay.h"
#include "cOsdDownloadingFilesMenu.h"
#include "cMLDonkeyAction.h"

#include "display.h"
#include "global.h"

#include "LogMsg.h"

/*--- Definition des macros instructions ---*/

/*--- Definition des structures privees ---*/

/*--- Definition des constantes privees ---*/

/*--- Definition des variables privees ---*/

/*--- Definition des variables globales ---*/

/*--- Definition des fonctions privees ---*/
static int g_key;

sem_t g_sem_key;
sem_t g_sem_Rx_ThreadFinish;


/*--- Definition des fonctions publiques ---*/

#define COLORS 14
#define WIDTH  10
#define HEIGHT 20

static bool running = false, stopped, ThreadRxFinish;



/*******************************************************************
 *              
 *  FUNCTION:   MlDkGuiRx_Thread
 *              
 *  RETURNS:    void *
 *              
 *  PARAMETERS: 
 *		Input  :
 *          void *pParam
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void * MlDkGuiRx_Thread(void *pParam)
{
	ThreadParamMlDkGuiRx *pParamMlDkGuiRx;

	pParamMlDkGuiRx = (ThreadParamMlDkGuiRx *)pParam;

	Word8 buf[400];
	Word32 siz;

	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : ThreadRx Start (%x,%x)\n",pParamMlDkGuiRx->pSocketGUI,pParamMlDkGuiRx->pMLDonkeyStatus);

	while(ThreadRxFinish == false)
	{
//		pParamMlDkGuiRx->pSocketGUI->WaitReceive();
		siz = pParamMlDkGuiRx->pSocketGUI->Receive(buf,390);
        if( ThreadRxFinish == false)
        {
    //		LogMsg(LOGLEVEL_SOCKET,"MlDkGUI : ThreadRx Receive %d\n",siz);
			pParamMlDkGuiRx->pMLDonkeyStatus->Analyse(buf,siz);
	   }
	}

    LogMsg(LOGLEVEL_MAIN,"MlDkGUI : ThreadRx Finish\n");

	sem_post(&g_sem_Rx_ThreadFinish);
	return(0);
}

/*******************************************************************
 *              
 *  FUNCTION:   MlDkGuiMain_Thread
 *              
 *  RETURNS:    void *
 *              
 *  PARAMETERS: 
 *		Input  :
 *          void *pParam
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void * MlDkGuiMain_Thread(void *pParam)
{
	ThreadParamMlDkGuiRx *param;
	pthread_t thr_id;
	cItemAction *cur_action;
	Word8 bufsend[1000];
	int sz;

//    cOsdBasicDisplay;

    cOsdBasicDisplay *pCurrentScreen,*pNextScreen;

	int X, Y, W, H;

//    x = (720 - (Setup.OSDwidth + 1) * charWidth) / 2;
//    y = (576 - Setup.OSDheight * lineHeight) / 2;

	W = 560;
	H = 280;
	X = 50;
	Y = 50;


	ThreadRxFinish = false;


	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Thread Start\n");

    sem_init(&g_sem_key,0,0);
	sem_init(&g_sem_Rx_ThreadFinish,0,0);

	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Dpy::open %d \n",Dpy::open(X, Y, W, H,1) );

	class cMLDonkeyAction MLDonkey;
	class cSocketM cSocketGUI;

	Dpy::message_show("Connecting to core", NULL , COL_WHT);
    Dpy::update();

	strcpy(g_CoreHostName , "10.0.0.10");
	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Try connect to %s:%d\n",g_CoreHostName, g_CorePort );

	cSocketGUI.Create();
	if( !cSocketGUI.Connect( g_CoreHostName, g_CorePort ) )
    {
	    Dpy::message_show("!! Fail to connect !!", NULL , COL_WHT);
        Dpy::update();

		LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Connection to core fail\n" );

        sem_wait(&g_sem_key);
    }
    else
    {
	    Dpy::message_show("Connection successful", NULL , COL_WHT);
        Dpy::update();

		LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Connection to core successful\n" );

	    param = (ThreadParamMlDkGuiRx *)malloc(sizeof (ThreadParamMlDkGuiRx));

	    param->pMLDonkeyStatus = &MLDonkey;
	    param->pSocketGUI = &cSocketGUI;

	    pthread_create(&thr_id, NULL, &MlDkGuiRx_Thread, (void *)param);
	    pthread_detach(thr_id);

		sz = MLDonkey.PrepareMessage2Core(OPCODES_TO_CORE_GUIPROTOCOLVERSION,bufsend,1000);
		cSocketGUI.Send(bufsend,sz);

		sz = MLDonkey.PrepareMessage2Core(OPCODES_TO_CORE_SENDPASSWD,bufsend,1000);
		cSocketGUI.Send(bufsend,sz);

        cItemAction     ActionViewMainMenu(ACTION_VIEW_MAINMENU);


	    stopped = false;

		pCurrentScreen = MLDonkey.ProcessAction( &ActionViewMainMenu );
//		pCurrentScreen->SetBackAction( &g_ActionExit );
//		last_action = &g_ActionViewMainMenu ;
		pCurrentScreen->Draw();

    	g_key = KEY_NONE;
	    while (running)
        {
			sz = MLDonkey.PrepareMessage2Core(OPCODES_TO_CORE_GETDOWNLOADINGFILES,bufsend,1000);
			cSocketGUI.Send(bufsend,sz);
			sz = MLDonkey.PrepareMessage2Core(OPCODES_TO_CORE_GETCONNECTEDSERVERS,bufsend,1000);
			cSocketGUI.Send(bufsend,sz);

            sem_wait(&g_sem_key);

			cur_action = pCurrentScreen->ProcessKey(g_key);
			if(  cur_action != NULL )
			{
                if( cur_action->m_Type == ACTION_EXIT)
                {
					ThreadRxFinish = true;
                	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Wait until Rx Thread Finish...\n");
					sem_wait(&g_sem_Rx_ThreadFinish);
                	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Rx Thread Finish !\n");
                    running = false;
                }
                else
                {
				    pNextScreen = MLDonkey.ProcessAction( cur_action );
                    if(pNextScreen != NULL)
                    {
                        pCurrentScreen = pNextScreen;
    //				    pCurrentScreen->SetBackAction( last_action );
    //				    last_action = cur_action;
		                pCurrentScreen->Draw();
                    }
                }
			}
    		g_key = KEY_NONE;
	    }

		free(param);

    }

	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Dpy::close\n");
	Dpy::close();
	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Dpy::close Ok\n");

	stopped = true;
	return (0);
}

/*******************************************************************
 *              
 *  FUNCTION:   MldkGUI_stop
 *              
 *  RETURNS:    int
 *              
 *  PARAMETERS: 
 *		Input  :
 *          void
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
int MldkGUI_stop(void)
{
	running = false;
	while (!stopped)
        usleep(10000);
	return (0);
}

/*******************************************************************
 *              
 *  FUNCTION:   MldkGUI_key
 *              
 *  RETURNS:    int
 *              
 *  PARAMETERS: 
 *		Input  :
 *          int k
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
int MldkGUI_key(int k)
{
    int ret = 0;

    if( running == true )
    {
		g_key = k;                    // XXX maybe mutex lock or cond signal?
		sem_post(&g_sem_key);
		ret=0;
    }
    else
    {
        ret=1;
    }
	return (ret);

//	if (key == KEY_BACK)
//    {
//		MldkGUI_stop();
//		return (1);
//	}
}



/*******************************************************************
 *              
 *  FUNCTION:   MldkGUI_start
 *              
 *  RETURNS:    int
 *              
 *  PARAMETERS: 
 *		Input  :
 *          void
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
int MldkGUI_start(void)
{
    if( running == false )
    {
        running = true;

	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : MldkGUI_start\n");

	pthread_t thr_id;
	pthread_create(&thr_id, NULL, &MlDkGuiMain_Thread, NULL);
	pthread_detach(thr_id);
    }
    else
    {
        LogMsg(LOGLEVEL_MAIN,"MlDkGUI : MldkGUI_start fail : Mldkgui run already \n");	
    }

	return (1);
}
