

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of PSYCLONE 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/
//_/_/
//_/_/  PSYCLONE 2.0 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.0 is also available to 
//_/_/  any interested party from the copyright holder.
//_/_/  
//_/_/  You can redistribute this copy of PSYCLONE 2.0 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.0.  
//_/_/  If not, see <http://www.gnu.org/licenses/>.
//_/_/  
//_/_/  PSYCLONE 2.0 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.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(_CCMCATALOG_H_)
#define _CCMCATALOG_H_

#include "PsyAPI.h"
#include "Observations.h"
#include "MathClasses.h"
#include "Bitmap.h"

namespace	cmlabs {

extern "C" {
	DllExport int8 CCMCatalog(PsyAPI* api);
	DllExport int8 CCMCollector(PsyAPI* api);
}


bool ProcessObservationTrigger(DataMessage* outMsg, DataMessage* inMsg, const ObsEntry &obsEntry, std::map<std::string, std::string>& mappings, uint64 id);

class CCMBaseTypedStorage {
public:
	virtual bool query(DataMessage* msg, DataMessage* resultMsg, std::list<std::string>* jsonList, uint32 lastObjectID) = 0;
	virtual bool addObservation(uint64 id, const char* cdata, uint32 size) = 0;
};

template <typename T>
class CCMTypedStorage : public CCMBaseTypedStorage {
public:
	CCMTypedStorage();
	~CCMTypedStorage();

	bool query(DataMessage* msg, DataMessage* resultMsg, std::list<std::string>* jsonList, uint32 lastObjectID);
	bool addObservation(uint64 id, const char* cdata, uint32 size);

protected:
	utils::Mutex mutex;
	std::multimap<uint64, GenericObservation<T>* > data;

	bool getRange(uint64 fromTime, uint64 toTime, T& from, T& to, uint64 creatorID, uint64 objectID, uint64 topicID, DataMessage* resultMsg, std::list<std::string>* jsonList);
	bool getPeriod(uint64 fromTime, uint64 toTime, uint64 creatorID, uint64 objectID, uint64 topicID, DataMessage* resultMsg, std::list<std::string>* jsonList);
	bool getLast(uint32 count, uint64 creatorID, uint64 objectID, uint64 topicID, DataMessage* resultMsg, std::list<std::string>* jsonList);
	bool getLastAllObjects(uint32 count, uint32 maxObjID, uint64 creatorID, uint64 topicID, DataMessage* resultMsg, std::list<std::string>* jsonList);
};

class CCMMap {
public:
	CCMMap() {
		image = NULL;
		parent = 0;
	}
	~CCMMap() {
		delete image;
		image = NULL;
	}

	std::string toJSON() {
		return utils::StringFormat("{ \"id\": %u, \"name\": \"%s\", \"width\": %.3f, \"height\": %.3f, \"offsetx\": %.3f, \"offsety\": %.3f, \"scalex\": %.3f, \"scaley\": %.3f }\n",
			id, name.c_str(), size.w, size.h, offset.x, offset.y, scale.x, scale.y);
	}

	uint32 id;
	std::string name;
	Size size;
	uint32 parent;
	PointFloat offset;
	Vector2D scale;
	Bitmap* image;
};

class CCMIdentity {
public:
	CCMIdentity() {
		image = face = NULL;
	}
	~CCMIdentity() {
		delete image;
		delete face;
		image = face = NULL;
	}

	std::string toJSON() {
		return utils::StringFormat("{ \"id\": %u, \"name\": \"%s\", \"type\": \"%s\", \"nickname\": \"%s\" }\n",
			id, name.c_str(), type.c_str(), nickname.c_str());
	}

	uint32 id;
	std::string name;
	std::string type;
	std::string nickname;
	Bitmap* image;
	Bitmap* face;
};

class CCMObject {
public:
	CCMObject() {
		id = 0;
		identity = 0;
		firstSeen = lastSeen = 0;
		presentNow = false;
	}
	~CCMObject() {
	}

	std::string toJSON() {
		return utils::StringFormat("{ \"id\": %u, \"type\": \"%s\", \"identity\": %u, \"firstseen\": %llu, \"lastseen\": %llu, \"present\": %u  }\n",
			id, type.c_str(), identity, firstSeen, lastSeen, presentNow ? "1" : "0");
	}

	uint32 id;
	std::string type;
	uint32 identity;
	uint64 firstSeen;
	uint64 lastSeen;
	bool presentNow;
};

class CCMImage {
public:
	CCMImage() {
		id = 0;
		createdTime = GetTimeNow();
		systemID = objectID = 0;
		image = NULL;
	}
	~CCMImage() {
		delete image;
		image = NULL;
	}

	std::string toJSON() {
		return utils::StringFormat("{ \"id\": %u, \"created\": %llu, \"system\": %u, \"object\": %u, \"size\": %u }\n",
			id, createdTime, systemID, objectID, image ? image->size : 0);
	}

	uint32 id;
	uint64 createdTime;
	uint32 systemID;
	uint32 objectID;
	Bitmap* image;
};

class CCMDataStorage {
public:
	CCMDataStorage();
	~CCMDataStorage();

	std::string init(const char* ccmDir);

	std::string addMap(const char* name, const char* size, const char* parent, const char* offset, const char* scale, const char* image);
	std::string addIdentity(const char* name, const char* type, const char* nickname, const char* image, const char* face);
	uint32 createObject(const char* type, uint32 identity, uint64 firstSeen, uint64 lastSeen, bool presentNow);
	bool addImage(uint32 objectID, uint32 systemID, Bitmap* image);

	std::string getFullJSON();
	bool queryMap(DataMessage* msg, DataMessage* replyMsg);
	bool queryIdentity(DataMessage* msg, DataMessage* replyMsg);
	bool queryObject(DataMessage* msg, DataMessage* replyMsg);
	CCMImage* getLastImage(uint32 objectID, uint32 systemID);

	bool query(DataMessage* qMsg, DataMessage* resultMsg, std::list<std::string>* jsonList = NULL);
	bool addObservation(const char* cdata, uint32 size);

protected:

	uint32 lastObsID;
	std::map<uint32, CCMBaseTypedStorage*> obsMap;
	std::string ccmDir;
	uint32 lastMapID;
	std::map<uint32, CCMMap*> maps;
	uint32 lastIdentityID;
	std::map<uint32, CCMIdentity*> identities;
	uint32 lastObjectID;
	std::map<uint32, CCMObject*> objects;
	uint32 lastImageID;
	std::map<uint32, CCMImage*> images;
};


} // namespace cmlabs

#include "CCMCatalog.tpl.h"

#endif // _CCMCATALOG_H_
