

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - 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. 
//_/_/
//_/_/  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 "Subscriptions.h"

namespace cmlabs {


RetrieveSpec* TriggerSpec::getRetrieveSpec(const char* name) {
	if (!name || !strlen(name) || !retrieveCount)
		return NULL;

	RetrieveSpec* spec = (RetrieveSpec*) (((char*)this) +
		sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)));

	uint32 n = 0;
	for (n = 0; n < retrieveCount; n++) {
		if (stricmp(name, spec->name) == 0)
			return spec;
		spec++;
	}
	return NULL;
}

QuerySpec* TriggerSpec::getQuerySpec(const char* name) {
	if (!name || !strlen(name) || !queryCount)
		return NULL;

	QuerySpec* spec = (QuerySpec*) (((char*)this) +
		sizeof(TriggerSpec) + (filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)));

	uint32 n = 0;
	for (n = 0; n < queryCount; n++) {
		if (stricmp(name, spec->name) == 0)
			return spec;
		spec++;
	}
	return NULL;
}

std::list<PostSpec*>* TriggerSpec::getPostSpecs(const char* name) {
	std::list<PostSpec*>* postSpecs = new std::list<PostSpec*>;
	uint32 n = 0;
	PostSpec* spec = (PostSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)));

	for (n = 0; n < postCount; n++) {
		if (!name || !strlen(name) || stricmp(name, spec->name) == 0)
			postSpecs->push_back(spec);
		spec++;
	}
	return postSpecs;
}

std::list<PostSpec*>* TriggerSpec::getPostSpecs(PsyType type) {
	std::list<PostSpec*>* postSpecs = new std::list<PostSpec*>;
	if (!type.isValid())
		return postSpecs;
	uint32 n = 0;
	PostSpec* spec = (PostSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)));

	for (n = 0; n < postCount; n++) {
		if (type.matches(spec->type))
			postSpecs->push_back(spec);
		spec++;
	}
	return postSpecs;
}
	
PostSpec* TriggerSpec::getPostSpec(const char* name) {
	uint32 n = 0;
	PostSpec* spec = (PostSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)));

	for (n = 0; n < postCount; n++) {
		if (stricmp(name, spec->name) == 0)
			return spec;
		spec++;
	}
	return NULL;
}


PostSpec* TriggerSpec::getPostSpec(PsyType type) {

	if (!type.isValid())
		return NULL;

	uint32 n = 0;
	PostSpec* spec = (PostSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)));

	for (n = 0; n < postCount; n++) {
		if (type.matches(spec->type))
			return spec;
		spec++;
	}
	return NULL;
}

SignalSpec* TriggerSpec::getSignalSpec(const char* name) {
	uint32 n = 0;
	SignalSpec* spec = (SignalSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)) +
		(postCount*sizeof(PostSpec)));

	for (n = 0; n < signalCount; n++) {
		if (stricmp(name, spec->name) == 0)
			return spec;
		spec++;
	}
	return NULL;
}


SignalSpec* TriggerSpec::getSignalSpec(PsyType type) {

	if (!type.isValid())
		return NULL;

	uint32 n = 0;
	SignalSpec* spec = (SignalSpec*) (((char*)this) +
		sizeof(TriggerSpec) +
		(filterCount*sizeof(FilterSpec)) +
		(retrieveCount*sizeof(RetrieveSpec)) +
		(queryCount*sizeof(QuerySpec)) +
		(postCount*sizeof(PostSpec)));

	for (n = 0; n < signalCount; n++) {
		if (type.matches(spec->type))
			return spec;
		spec++;
	}
	return NULL;
}



std::string TriggerSpec::toXML() {
	uint32 n;
	std::string str = utils::StringFormat("<trigger name=\"%s\" type=\"%s\" compid=\"%u\" interval=\"%u\" delay=\"%u\" from=\"%u\" to=\"%u\" tag=\"%u\" filtercount=\"%u\" signalcount=\"%u\" postcount=\"%u\" context=\"%s\" triggercontext=\"%s\"",
		name, type.toString().c_str(), componentID, interval, delay, from, to, tag, filterCount, signalCount, postCount, context.toString().c_str(), triggerContext.toString().c_str());

	if (!retrieveCount && !queryCount && !filterCount && !signalCount && !postCount) {
		str += " />\n";
		return str;
	}
	else
		str += ">\n";

	for (n=0; n<retrieveCount; n++) {
		RetrieveSpec* rSpec = getRetrieveSpec(n);
		if (rSpec)
			str += rSpec->toXML();
	}

	for (n=0; n<signalCount; n++) {
		SignalSpec* sSpec = getSignalSpec(n);
		if (sSpec)
			str += sSpec->toXML();
	}

	for (n=0; n<queryCount; n++) {
		QuerySpec* qSpec = getQuerySpec(n);
		if (qSpec)
			str += qSpec->toXML();
	}

	for (n=0; n<postCount; n++) {
		PostSpec* pSpec = getPostSpec(n);
		if (pSpec)
			str += pSpec->toXML();
	}

	str += "</trigger>\n";
	return str;

}

} // namespace cmlabs
