

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of PSYCLONE version 2.1.1.260726 (26 July 2026)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2026
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  PSYCLONE 2.1 is released under the GNU Lesser General Public License 
//_/_/  (LGPL) version 3.0, and is subject to the following
//_/_/  
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/    
//_/_/  A commercial license for PSYCLONE 2.1 is also available to 
//_/_/  any interested party from the copyright holder.
//_/_/  
//_/_/  You can redistribute this copy of PSYCLONE 2.1 and/or modify it under 
//_/_/  the terms of the GNU General Public License as published by the Free 
//_/_/  Software Foundation, either version 3 of the License, or (at your 
//_/_/  option) any later version.
//_/_/  
//_/_/  You should have received a copy of the GNU General Public License
//_/_/  and the GNU Lesser General Public License along with PSYCLONE 2.1.  
//_/_/  If not, see <http://www.gnu.org/licenses/>.
//_/_/  
//_/_/  PSYCLONE 2.1 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.
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#include "Whiteboard.h"

namespace	cmlabs {

int8 Whiteboard(PsyAPI* api) {
	char* myName = new char[256];
	api->getModuleName(myName, 256);

	api->setPrivateData("MyStatus", "Hello World", 12);
	api->addPsyProbeCustomView("Stored Messages", "elements/whiteboardmessages.html");

	api->logPrint(2,"Started running...");

	MessageIndex index;
	index.addIndexKey("time", INDEX_TIME);

	uint32 keepMS = (uint32)api->getParameterInt("KeepMS");
	if (keepMS)
		index.setDefaultTTL(keepMS*1000);

	char* keys = new char[MAXVALUENAMELEN+1];
	if (api->getParameter("keys", keys, MAXVALUENAMELEN)) {
		std::multimap<std::string, std::string> keymap = utils::TextMultiMapSplit(keys, ";", "=");
		std::multimap<std::string, std::string>::iterator i = keymap.begin(), e = keymap.end();
		while (i != e) {
			if (stricmp(i->second.c_str(), "string") == 0)
				index.addIndexKey(i->first.c_str(), INDEX_STRING);
			else if (stricmp(i->second.c_str(), "integer") == 0)
				index.addIndexKey(i->first.c_str(), INDEX_INTEGER);
			else if (stricmp(i->second.c_str(), "float") == 0)
				index.addIndexKey(i->first.c_str(), INDEX_FLOAT);
			else if (stricmp(i->second.c_str(), "double") == 0)
				index.addIndexKey(i->first.c_str(), INDEX_FLOAT);
			else if (stricmp(i->second.c_str(), "time") == 0)
				index.addIndexKey(i->first.c_str(), INDEX_TIME);
			i++;
		}
	}
	delete [] keys;

	DataMessage* inMsg;
	uint32 size, count, c = 0;
	char* result;
	RetrieveSpec* retrieveSpec;
	const char* triggerName;
	while (api->shouldContinue()) {
		if ( inMsg = api->waitForNewMessage(200, triggerName)) {
			if (triggerName && stricmp(triggerName, "DefaultComponentTrigger") == 0)
				api->logPrint(2,"Got wakeup message...");
			else if (inMsg->getType() == PsyAPI::CTRL_QUERY) {
				if (retrieveSpec = (RetrieveSpec*) inMsg->getData("RetrieveSpec", size)) {
					result = index.queryMessages(retrieveSpec, size, count);
					api->logPrint(2,"Retrieved %u (of %u) msgs on request from %u (%s)...", count, index.getCount(), retrieveSpec->origin, retrieveSpec->name);
					if (count)
						api->queryReply((uint32)inMsg->getReference(), QUERY_SUCCESS, result, size, count);
					else
						api->queryReply((uint32)inMsg->getReference(), QUERY_SUCCESS);
					free(result);
				}
				else {
					api->queryReply((uint32)inMsg->getReference(), QUERY_FAILED);
				}
			}
			else {
				// Received a message to go into the Index
				index.addMessage(new DataMessage((char*)inMsg->data, true));
				api->logPrint(3,"Added msg %u   %s", ++c, PrintTimeString(inMsg->getCreatedTime()).c_str());
			}
		}
	}

	delete [] myName;
	return 0;
}

} // namespace cmlabs
