/*
	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 "ZMWSMonitorPlugins.h"
#include <map>
#include <string>

typedef	 void		(*plg_fn)				(void);
typedef	 char**		(*get_plg_fn_names)		(void);

typedef struct _PluginEntry {
	std::string plg_name;
	std::string fn_name;
	plg_fn plg_fn;
} PluginEntry;

typedef std::pair<WORD, PluginEntry> PluginEntryPair;
typedef std::map<WORD, PluginEntry> PluginEntriesMap;
typedef PluginEntriesMap::iterator PluginEntriesIterator;

PluginEntriesMap PluginEntries;


void ZMWSMonitorLoadPlugins () {
	WIN32_FIND_DATA fileData;
	get_plg_fn_names ZPluginGetInterface;
	WORD msg = WM_USER;
	HANDLE handle = FindFirstFile("_plugins.zmwsc/*.plg", &fileData);
	
	while (INVALID_HANDLE_VALUE != handle) {
		HMODULE hPlugin = LoadLibrary ((std::string("_plugins.zmwsc/")+fileData.cFileName).c_str());
		if (hPlugin) {
			ZPluginGetInterface = (get_plg_fn_names)GetProcAddress(hPlugin, "ZPluginGetInterface");
			if (ZPluginGetInterface) {
				PluginEntry pe;
				char** strings = ZPluginGetInterface();
				int i = 0;
				if (strings[i])	{
					pe.plg_name = strings[i];
					++i;
					while (strings[i] && strings[i+1]) {
						pe.fn_name = strings[i];
						pe.plg_fn = (plg_fn)GetProcAddress(hPlugin, strings[i+1]);
						if (pe.plg_fn) {
							PluginEntries.insert(PluginEntryPair(msg++, pe));
						}
						i += 2;
					}
				}
			}
		}
		if (!FindNextFile(handle, &fileData)) {
			break;
		}
	}

	FindClose(handle);
}

void ZMWSMonitorAddPlugins(HMENU popupMenu, int pos) {
	MENUITEMINFO menuiteminfo;
	HMENU pluginsMenu = CreateMenu ();
	std::string curPlugin;

	if (pluginsMenu) {
		memset (&menuiteminfo, 0, sizeof(MENUITEMINFO));
		menuiteminfo.cbSize = sizeof(MENUITEMINFO);
		menuiteminfo.fMask = MIIM_STATE | MIIM_SUBMENU;
		menuiteminfo.fState = MFS_ENABLED;
		menuiteminfo.hSubMenu = pluginsMenu;
		SetMenuItemInfo (popupMenu, pos, TRUE, &menuiteminfo);

		PluginEntriesIterator it;
		UINT menupos = 0;
		UINT curPluginPos = 0;
		HMENU curPluginMenu;
		for (it = PluginEntries.begin(); it!=PluginEntries.end(); ++it) {
			if (curPlugin != it->second.plg_name) {
				curPlugin = it->second.plg_name;
				menupos = 0;

				curPluginMenu = CreateMenu();
				memset (&menuiteminfo, 0, sizeof(MENUITEMINFO));
				menuiteminfo.cbSize = sizeof(MENUITEMINFO);
				menuiteminfo.fMask = MIIM_STRING | MIIM_SUBMENU;
				menuiteminfo.dwTypeData = (LPSTR)(it->second.plg_name.c_str());
				menuiteminfo.hSubMenu = curPluginMenu;
				InsertMenuItem (pluginsMenu, curPluginPos++, TRUE, &menuiteminfo);
			}
			memset (&menuiteminfo, 0, sizeof(MENUITEMINFO));
			menuiteminfo.cbSize = sizeof(MENUITEMINFO);
			menuiteminfo.fMask = MIIM_STRING | MIIM_ID;
			menuiteminfo.dwTypeData = (LPSTR)(it->second.fn_name.c_str());
			menuiteminfo.wID = it->first;
			InsertMenuItem (curPluginMenu, menupos++, TRUE, &menuiteminfo);
		}
	}
}

void ZMWSMonitorInvokePluginFn(WORD id) {
	PluginEntriesIterator pei = PluginEntries.find(id);
	if (pei != PluginEntries.end()) {
		pei->second.plg_fn();
	}
}
