/*
	ZazouMiniWebServer

	Copyright (C) 2003-2009 Xavier Garreau <xavier@xgarreau.org>

	This file is part of ZazouMiniWebServer.

    ZazouMiniWebServer 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.

    ZazouMiniWebServer 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 ZazouMiniWebServer; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

#include "stdafx.h"
#include <string>
#include <sstream>
#include "ZazouMiniWebServerMonitor.h"
#include "ZMWSConsole.h"
#include "ZMWSMonitorSplash.h"
#include "ZMWSMonitorPlugins.h"


#define MAX_LOADSTRING 100
#define ZWMS_MESSAGE WM_USER

// Variables globales :
// ToDo: A mettre dans une structure ?
static HINSTANCE g_hInst;								// instance actuelle
static HWND g_hWnd;										// notre fenêtre
static CHAR g_szTitle[MAX_LOADSTRING];					// Le texte de la barre de titre
static CHAR g_szWindowClass[MAX_LOADSTRING];			// le nom de la classe de fenêtre principale
CBaseZMWSConfig	zmws_base_config;						// La configuration du serveur
static UINT ZMWSSTOPMESSAGE;

// Pré-déclarations des fonctions incluses dans ce module de code :
BOOL				InitInstance (HINSTANCE, int);
LRESULT CALLBACK	WndProc (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
void				AddTrayIcon ();

int APIENTRY WinMain(HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPTSTR    lpCmdLine,
					 int       nCmdShow)
{
	NOTIFYICONDATA nid;
	MSG msg;
	HACCEL hAccelTable;

	// Initialise les chaînes globales
	LoadString(hInstance, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_ZAZOUMINIWEBSERVERMONITOR, g_szWindowClass, MAX_LOADSTRING);

	// Effectue l'initialisation de l'application :
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	ShowSplash(hInstance, g_hWnd, 2000);

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_ZAZOUMINIWEBSERVERMONITOR);
	
	// Ajoute l'icône au tray
	AddTrayIcon ();

	// Lance le serveur
	LPSTR cmdLine = GetCommandLine();
	LPSTR cmdOpts = lpCmdLine;
	while (cmdOpts[strlen(cmdOpts)-1]==' ') cmdOpts[strlen(cmdOpts)-1]='\0';
	size_t lenLine = strlen(cmdLine);
	size_t lenOpts = strlen(cmdOpts);
	int argc = 1;
	size_t i;
	if (lenOpts) {
		++argc;
		for (i=0; i<lenOpts; ++i) {
			if (cmdOpts[i]==' ') {
				cmdOpts[i] = 0;
				++argc;
				while (i<lenOpts && cmdOpts[i+1]==' ') ++i;
			}
		}
	}
	char** argv = (char**)malloc(argc*sizeof(char*));
	int j;
	argv[0] = cmdLine;
	cmdLine[lenLine-lenOpts-1] = 0;
	while (cmdLine[strlen(cmdLine)-1]==' ') cmdLine[strlen(cmdLine)-1]='\0';
	for (j=1; j<argc; ++j) {
		argv[j] = cmdOpts;
		cmdOpts += strlen (cmdOpts)+1;
		while (*cmdOpts && *cmdOpts==' ') ++cmdOpts;
	}

	int res = zmws_start (argc, argv);
	int stopMySQL = 0;

	if (res) {
		// Lance MySQL
		if (ZMWSFileExists("mysql_start.bat")) {
			ShellExecute (NULL, NULL, "mysql_start.bat", NULL, NULL, SW_HIDE);
			stopMySQL = 1;
		}
	}


	memset (&zmws_base_config, 0, sizeof(zmws_base_config));
	zmws_get_config (&zmws_base_config);

	if (!res) {
		if (!zmws_base_config.beQuiet) {
			res = 1;
			zmws_stop();
			CreateConsole ();
			zmws_start (argc, argv);
		}
	}

	if (res) {
		ZMWSSTOPMESSAGE = RegisterWindowMessage (LPCTSTR("ZazouMiniWebServerStop"));

		// Boucle de messages principale :
		while (GetMessage(&msg, NULL, 0, 0)) 
		{
			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}

	}

	// Stoppe MySQL
	if (stopMySQL && ZMWSFileExists("mysql_stop.bat")) {
		ShellExecute (NULL, NULL, "mysql_stop.bat", NULL, NULL, SW_HIDE);
	}

	zmws_stop ();

	// Supprime l'icône du tray
	nid.cbSize = sizeof(NOTIFYICONDATA);
	nid.hWnd = g_hWnd;
	nid.uID = 1;
	Shell_NotifyIcon(NIM_DELETE, &nid);

	return (int) msg.wParam;
}

//
//   FONCTION : InitInstance(HANDLE, int)
//
//   BUT : enregistre le handle de l'instance et crée une fenêtre principale
//
//   COMMENTAIRES :
//
//        Dans cette fonction, nous enregistrons le handle de l'instance dans une variable globale, puis
//        créons et affichons la fenêtre principale du programme.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	WNDCLASSEX wcex;

	g_hInst = hInstance; // Stocke le handle d'instance dans la variable globale
	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(g_hInst, (LPCTSTR)IDI_ZAZOUMINIWEBSERVERMONITOR);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= 0;
	wcex.lpszClassName	= g_szWindowClass;
	wcex.hIconSm		= LoadIcon(g_hInst, (LPCTSTR)IDI_ZAZOUMINIWEBSERVERMONITOR);

	if (RegisterClassEx(&wcex)) {
		g_hWnd = CreateWindow(g_szWindowClass, g_szTitle, 0, 0, 0, 0, 0, NULL, NULL, g_hInst, NULL);

		if (!g_hWnd)
		{
			return FALSE;
		}
	}

	return TRUE;

}

void AddTrayIcon () {
	NOTIFYICONDATA nid;
	nid.cbSize = sizeof(NOTIFYICONDATA);
	nid.hWnd = g_hWnd;
	nid.uID = 1;
	nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
	nid.hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ZAZOUMINIWEBSERVERMONITOR), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
	strcpy (nid.szTip, "ZazouMiniWebServer");
	nid.uCallbackMessage = ZWMS_MESSAGE;
	Shell_NotifyIcon(NIM_ADD, &nid);
}
//
//  FONCTION : WndProc(HWND, unsigned, WORD, LONG)
//
//  BUT :  traite les messages pour la fenêtre principale.
//
//  WM_COMMAND	- traite le menu de l'application
//  WM_DESTROY	- génère un message d'arrêt et retourne
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	HMENU hMenu, popupMenu;
	HWND hAboutDlg;
	static BOOL isConsoleShown = false;
	static UINT g_uTaskbarRestart;

	switch (message) 
	{
		case WM_CREATE:
			// Merci Darius :)
			g_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));

			// Charge d'éventuels plugins
			ZMWSMonitorLoadPlugins ();
			break;
		case ZWMS_MESSAGE:
			switch (lParam) {
				case WM_LBUTTONDBLCLK:
					//DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)AboutDlgProc);
					hAboutDlg = CreateDialog(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)AboutDlgProc);
					if (hAboutDlg) {
#ifdef ZAZOUNT
						ShowWindow (hAboutDlg, SW_SHOW);
#else
						AnimateWindow (hAboutDlg, 500, AW_ACTIVATE | AW_BLEND);
#endif
					}
					break;
				case WM_RBUTTONUP:
					hMenu = LoadMenu (g_hInst, (LPCTSTR)IDR_ZMWS_TB_MENU);
					if (hMenu) {
						if (isConsoleShown) {
							CheckMenuItem(hMenu, IDM_TB_CONSOLE, MF_BYCOMMAND | MF_CHECKED);
						}
						if (ZMWSFileExists(zmws_base_config.pathToConfigFile)) {
							EnableMenuItem (hMenu, IDM_TB_CONFIG, MF_BYCOMMAND | MF_ENABLED);
						}
						if (strlen(zmws_base_config.pathToPHP) && ZMWSFileExists("_utils.zmwsc/editpi.scr")) {
							EnableMenuItem (hMenu, IDM_TB_PHPINI, MF_BYCOMMAND | MF_ENABLED);
						}
						if (ZMWSFileExists("_utils.zmwsc/mysql_start.bat")) {
							EnableMenuItem (hMenu, IDM_TB_MYSQL_START, MF_BYCOMMAND | MF_ENABLED);
						}
						if (ZMWSFileExists("_utils.zmwsc/mysql_stop.bat")) {
							EnableMenuItem (hMenu, IDM_TB_MYSQL_STOP, MF_BYCOMMAND | MF_ENABLED);
						}
						popupMenu = GetSubMenu (hMenu, 0);
						if (popupMenu) {
							ZMWSMonitorAddPlugins(popupMenu, 6);
							POINT pt;
							GetCursorPos(&pt);
							SetForegroundWindow(hWnd);
							TrackPopupMenu(	popupMenu,
											TPM_RIGHTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON,
											pt.x, pt.y,
											0,
											hWnd,
											0);
							PostMessage(hWnd, WM_NULL, 0, 0);
						}
						DestroyMenu (hMenu);
					}
					break;
				default:
					break;
			}
			break;
		case WM_COMMAND:
			wmEvent = HIWORD(wParam); 
			wmId    = LOWORD(wParam); 
			// Analyse les sélections de menu :
			switch (wmId) {
				case IDM_ABOUT:
					hAboutDlg = CreateDialog(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)AboutDlgProc);
					if (hAboutDlg) {
#ifdef ZAZOUNT
						ShowWindow (hAboutDlg, SW_SHOW);
#else
						AnimateWindow (hAboutDlg, 500, AW_ACTIVATE | AW_BLEND);
#endif
					}
					break;
				case IDM_TB_AIDEENLIGNE:
					ShellExecute (NULL, NULL, "http://www.zmws.com/doc/", NULL, NULL, SW_SHOWNORMAL);
					break;
				case IDM_TB_RESTART: {
						int argc = 1;
						char* argv[] = {
							"ZazouMiniWebServerMonitor"
						};
						zmws_stop();
						if (!zmws_start (argc, argv)) {
							zmws_stop();
							CreateConsole ();
							zmws_start (argc, argv);
						}
						zmws_free_config (&zmws_base_config);
						memset (&zmws_base_config, 0, sizeof(zmws_base_config));
						zmws_get_config (&zmws_base_config);
					}
					break;
				case IDM_TB_QUITTER:
					DestroyWindow(hWnd);
					break;
				case IDM_TB_NAVIG:
					zmws_browse();
					break;
				case IDM_TB_CONSOLE:
					isConsoleShown = true;
					if (!CreateConsole()) {
						isConsoleShown = false;
						FreeConsole();
					}
					break;
				case IDM_TB_MYSQL_START:
					ShellExecute (NULL, NULL, "_utils.zmwsc/mysql_start.bat",
								NULL, NULL, SW_HIDE);
					break;
				case IDM_TB_MYSQL_STOP:
					ShellExecute (NULL, NULL, "_utils.zmwsc/mysql_stop.bat",
								NULL, NULL, SW_HIDE);
					break;
				case IDM_TB_DOCS:
					// Le passage par l'appel d'explorer est obligatoire
					// sinon, si on a un fichier exécutable portant le même nom que 
					// le répertoire à l'extension près, il est exécuté ...
					// Même si on passe "explore" en lpOperation
					ShellExecute (NULL, NULL, "explorer",
								zmws_base_config.documentRoot, NULL, SW_SHOWNORMAL);
					break;
				case IDM_TB_CONFIG:
					ShellExecute (NULL, NULL, "write",
								zmws_base_config.pathToConfigFile, NULL, SW_SHOWNORMAL);
					break;
				case IDM_TB_PHPINI:
					ShellExecute (NULL, NULL, zmws_base_config.pathToPHP,
								"-f _utils.zmwsc/editpi.scr", // EDIT Php.Ini . SCRipt
								NULL, SW_HIDE);
					break;
				default:
					ZMWSMonitorInvokePluginFn(wmId);
					break;
			}
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_ENDSESSION:
			zmws_stop ();
			return 0;
		default:
			if (message == g_uTaskbarRestart) {
				AddTrayIcon ();
			}
			if (message == ZMWSSTOPMESSAGE) {
				PostQuitMessage (0);
			}
			break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

// Gestionnaire de messages pour la boîte de dialogue à propos
LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	static HWND shownAboutDlg = NULL;
	char tmpS[1024];
	const char* zmws_version;

	switch (message)
	{
	case WM_INITDIALOG:
		if (shownAboutDlg != NULL) {
			SetForegroundWindow(shownAboutDlg);
			//EndDialog (hDlg, 0);
			DestroyWindow (hDlg);
			break;
		}

		strcpy (tmpS, "Version : ");
		zmws_version = zmws_get_version();
		if (strlen (zmws_version)) {
			strcat (tmpS, zmws_version);
		} else {
			strcat (tmpS, "?.?.?");
		}
		SetDlgItemText(hDlg, IDC_ABOUT_VERSION, tmpS);

		strcpy (tmpS, "IP : ");
		strcat (tmpS, zmws_get_ips());
		SetDlgItemText(hDlg, IDC_ABOUT_IP, tmpS);

		strcpy (tmpS, "PHP : ");
		if (strlen (zmws_base_config.pathToPHP)) {
			strcat (tmpS, "OK");
		} else {
			strcat (tmpS, "- KO -");
		}
		SetDlgItemText(hDlg, IDC_ABOUT_PHP, tmpS);

		strcpy (tmpS, "HTTP : ");
		if (zmws_base_config.port) {
			strcat (tmpS, "OK, port ");
			sprintf (tmpS+strlen(tmpS), "%d", zmws_base_config.port);
		} else {
			strcat (tmpS, "- KO -");
		}
		SetDlgItemText(hDlg, IDC_ABOUT_HTTP, tmpS);

		strcpy (tmpS, "HTTPS : ");
		if (zmws_base_config.sport) {
			strcat (tmpS, "OK, port ");
			sprintf (tmpS+strlen(tmpS), "%d", zmws_base_config.sport);
		} else {
			strcat (tmpS, "- KO -");
		}
		SetDlgItemText(hDlg, IDC_ABOUT_HTTPS, tmpS);

		shownAboutDlg = hDlg;
		break;

	case WM_COMMAND:
		wmEvent = HIWORD(wParam); 
		wmId    = LOWORD(wParam); 
		// Analyse les sélections de menu :
		switch (wmId)
		{
			case IDC_DONATE:
				ShellExecute (NULL, NULL, "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=xavier%40xgarreau%2eorg&item_name=Pack%20ZMWS&no_shipping=1&cn=Vos%20commentaires&tax=0&currency_code=EUR&bn=PP%2dDonationsBF&charset=UTF%2d8", NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDC_HOME:
				ShellExecute (NULL, NULL, "http://www.zmws.com/", NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDC_CHECK_VERSION:
				ShellExecute (NULL, NULL, "http://www.zmws.com/dl/", NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDC_FORUM:
				ShellExecute (NULL, NULL, "http://www.zmws.com/forum/", NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDC_SITE_ACCESSIBLE:
				char url[256];
				memset (url, 0, sizeof(url));
				strcpy (url, "http://www.zmws.com/utils/porttest.php?http=");
				sprintf (url+strlen(url), "%u", zmws_base_config.port & 0xffff);
				strcat(url, "&https=");
				sprintf (url+strlen(url), "%u", zmws_base_config.sport & 0xffff);
				ShellExecute (NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDC_IP_EXTERNE:
				ShellExecute (NULL, NULL, "http://www.zmws.com/utils/myip.php", NULL, NULL, SW_SHOWNORMAL);
				break;
			case IDOK:
			case IDCANCEL:
#ifdef ZAZOUNT
				ShowWindow (hDlg, SW_HIDE);
#else
				AnimateWindow (hDlg, 500, AW_BLEND | AW_HIDE);
#endif
				DestroyWindow (hDlg);
				shownAboutDlg = NULL;
				return TRUE;
			default:
				return DefWindowProc(hDlg, message, wParam, lParam);
		}
		break;
	}
	return FALSE;
}
