/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
 */

#include "MtpDebug.h"
#include "MtpStorage.h"
#include "MtpDataPacket.h"
#include "MtpServer.h"
#include "MtpEventPacket.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <sstream>

#define WATCH_FLAGS ( IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY )

static int mtpid = 0;

MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
		const char* description, uint64_t reserveSpace,
		bool removable, uint64_t maxFileSize, MtpServer* refserver)
	:	mStorageID(id),
		mFilePath(filePath),
		mDescription(description),
		mMaxCapacity(0),
		mMaxFileSize(maxFileSize),
		mReserveSpace(reserveSpace),
		mRemovable(removable),
		mServer(refserver)
{
	MTPI("MtpStorage id: %d path: %s\n", id, filePath);
	mtpparentid = 0;
	inotify_thread = 0;
	sendEvents = false;
	use_mutex = true;
	if (pthread_mutex_init(&mtpMutex, NULL) != 0) {
		MTPE("Failed to init mtpMutex\n");
		use_mutex = false;
	}
	if (pthread_mutex_init(&inMutex, NULL) != 0) {
		MTPE("Failed to init inMutex\n");
		use_mutex = false;
	}
	
}

MtpStorage::~MtpStorage() {
	if (inotify_thread) {
		pthread_kill(inotify_thread, 0);
		for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
			inotify_rm_watch(inotify_fd, i->first);
		}
		close(inotify_fd);
	}
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		delete i->second;
	}
	if (use_mutex) {
		use_mutex = false;
		pthread_mutex_destroy(&mtpMutex);
		pthread_mutex_destroy(&inMutex);
	}
}

int MtpStorage::getType() const {
	return (mRemovable ? MTP_STORAGE_REMOVABLE_RAM :  MTP_STORAGE_FIXED_RAM);
}

int MtpStorage::getFileSystemType() const {
	return MTP_STORAGE_FILESYSTEM_HIERARCHICAL;
}

int MtpStorage::getAccessCapability() const {
	return MTP_STORAGE_READ_WRITE;
}

uint64_t MtpStorage::getMaxCapacity() {
	if (mMaxCapacity == 0) {
		struct statfs   stat;
		if (statfs(getPath(), &stat))
			return -1;
		mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize;
	}
	return mMaxCapacity;
}

uint64_t MtpStorage::getFreeSpace() {
	struct statfs   stat;
	if (statfs(getPath(), &stat))
		return -1;
	uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
	return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
}

const char* MtpStorage::getDescription() const {
	return (const char *)mDescription;
}

int MtpStorage::createDB() {
	std::string mtpParent = "";
	mtpstorageparent = getPath();
	readParentDirs(getPath());
	while (!mtpParentList.empty()) {
		mtpParent = mtpParentList.front();
		mtpParentList.pop_front();
		readParentDirs(mtpParent);
	}
	MTPD("MtpStorage::createDB DONE\n");
	if (use_mutex) {
		MTPD("Starting inotify thread\n");
		sendEvents = true;
		inotify_thread = inotify();
	} else {
		MTPD("NOT starting inotify thread\n");
	}
	return 0;
}

MtpObjectHandleList* MtpStorage::getObjectList(MtpStorageID storageID, MtpObjectHandle parent) {
	std::vector<int> mtpids;
	int local_mtpparentid;
	MTPD("MtpStorage::getObjectList\n");
	MTPD("parent: %d\n", parent);
	//append object id  (numerical #s) of database to int array
	MtpObjectHandleList* list = new MtpObjectHandleList();
	if (parent == MTP_PARENT_ROOT) {
		MTPD("parent == MTP_PARENT_ROOT\n");
		local_mtpparentid = 1;
	}
	else {
		for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
			MTPD("root: %d\n", i->second->Root());
			Node* node = i->second->findNode(parent, i->second->Root());
			if (node != NULL) {
				local_mtpparentid = i->second->getMtpParentId(node);
				MTPD("path: %s\n", i->second->getPath(node).c_str());
				MTPD("mtpparentid: %d going to endloop\n", local_mtpparentid);
				goto endloop;
			}
		}
	}
	MTPD("got to endloop\n");
	endloop:

	if (mtpmap[local_mtpparentid] == NULL) {
		MTPD("mtpmap[mtpparentid] == NULL, returning\n");
		return list;
	}

	MTPD("root: %d\n", mtpmap[local_mtpparentid]->Root());
	mtpmap[local_mtpparentid]->getmtpids(mtpmap[local_mtpparentid]->Root(), &mtpids);
	MTPD("here, mtpids->size(): %i\n", mtpids.size());

	for (unsigned index = 0; index < mtpids.size(); index++) {
		MTPD("mtpidhere[%i]: %d\n", index, mtpids.at(index));
		list->push(mtpids.at(index));
	}
	return list;
}

int MtpStorage::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
	struct stat st;
	uint64_t size;
	MTPD("MtpStorage::getObjectInfo handle: %d\n", handle);
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		Node* node = i->second->findNode(handle, i->second->Root());
		MTPD("node returned: %d\n", node);
		if (node != NULL) {
				MTPD("found mtpid: %d\n", node->Mtpid());
				info.mStorageID = getStorageID();
				MTPD("info.mStorageID: %d\n", info.mStorageID);
				info.mParent = node->getMtpParentId();
				MTPD("mParent: %d\n", info.mParent);
				lstat(node->getPath().c_str(), &st);
				size = st.st_size;
				MTPD("size is: %llu\n", size);
				info.mCompressedSize = size;//(size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size);
				info.mDateModified = st.st_mtime;
				if (S_ISDIR(st.st_mode)) {
					info.mFormat = MTP_FORMAT_ASSOCIATION;
				}
				else {
					info.mFormat = MTP_FORMAT_UNDEFINED;
				}
				info.mName = strdup(basename(node->getPath().c_str()));
				MTPD("MtpStorage::getObjectInfo found, Exiting getObjectInfo()\n");
				return 0;
		}
	}
	// Item is not on this storage device
	return -1;
}

MtpObjectHandle MtpStorage::beginSendObject(const char* path,
											MtpObjectFormat format,
											MtpObjectHandle parent,
											MtpStorageID storage,
											uint64_t size,
											time_t modified) {
	MTPD("MtpStorage::beginSendObject(), path: '%s', parent: %d, storage: %d, format: %04x\n", path, parent, storage, format);
	Node* node;
	std::string parentdir;
	std::string pathstr(path);
	int parent_id;
	parentdir = pathstr.substr(0, pathstr.find_last_of('/'));
	MTPD("MtpStorage::beginSendObject() parentdir: %s\n", parentdir.c_str());
	if (parentdir.compare(mtpstorageparent) == 0) {
		// root directory
		MTPD("MtpStorage::beginSendObject() root dir\n");
		parent_id = 1;
		++mtpid;
		node = mtpmap[parent_id]->addNode(mtpid, path);
		MTPD("node: %d\n", node);
		node->addProperties(storage, 0);
		if (format == MTP_FORMAT_ASSOCIATION) {
			createEmptyDir(path);
		}
		return mtpid;
	} else {
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			node = i->second->findNodePath(parentdir, i->second->Root());
			if (node != NULL) {
				MTPD("mtpid: %d\n", mtpid);
				MTPD("path: %s\n", i->second->getPath(node).c_str());
				parentdir = i->second->getPath(node);
				parent = i->second->getMtpParentId(node);
				if (parent == 0) {
					MTPD("MtpStorage::beginSendObject parent is 0, error.\n");
					return -1;
				} else {
					++mtpid;
					node = mtpmap[parent]->addNode(mtpid, path);
					node->addProperties(getStorageID(), getParentObject(parentdir));
					for (iter i2 = mtpmap.begin(); i2 != mtpmap.end(); i2++) {
						node = i2->second->findNodePath(path, i2->second->Root());
						if (node != NULL) {
							i2->second->setMtpParentId(parent, node);
						}
					}
					if (format == MTP_FORMAT_ASSOCIATION) {
						createEmptyDir(path);
					}
				}
				return mtpid;
			}
		}
	}
	MTPE("MtpStorage::beginSendObject(), path: '%s', parent: %d, storage: %d, format: %04x\n", path, parent, storage, format);
	return -1;
}

int MtpStorage::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
	struct stat st;
	Node* node;
	MTPD("MtpStorage::getObjectFilePath handle: %i\n", handle);
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		MTPD("handle: %d\n", handle);
		node = i->second->findNode(handle, i->second->Root());
		MTPD("node returned: %d\n", node);
		if (node != NULL) {
			lstat(node->getPath().c_str(), &st);
			outFileLength = st.st_size;
			outFilePath = strdup(node->getPath().c_str());
			MTPD("outFilePath: %s\n", node->getPath().c_str());
			goto end;
		}
	}
	// Item is not on this storage
	return -1;
end:
	outFormat = MTP_FORMAT_ASSOCIATION;
	return 0;
}

int MtpStorage::readParentDirs(std::string path) {
	struct dirent *de;
	struct stat st;
	DIR *d;
	std::string parent, item, prevparent = "";
	Node* node;
	int storageID = getStorageID();

	d = opendir(path.c_str());
	MTPD("opening '%s'\n", path.c_str());
	if (d == NULL) {
		MTPD("error opening '%s' -- error: %s\n", path.c_str(), strerror(errno));
		closedir(d);
	}
	while ((de = readdir(d)) != NULL) {
		if (de->d_type == DT_DIR && strcmp(de->d_name, ".") == 0)
			continue;
		if (de->d_type == DT_DIR && strcmp(de->d_name, "..") != 0) {
			// Handle dirs
			item = path + "/" + de->d_name;
			MTPD("dir: %s\n", item.c_str());
			mtpParentList.push_back(item);
			parent = item.substr(0, item.find_last_of('/'));
			++mtpid;
			MTPD("parent: %s\n", parent.c_str());
			MTPD("mtpid: %d\n", mtpid);
			if (prevparent != parent) {
				mtpparentid++;
				MTPD("Handle dirs, prevparent != parent, mtpparentid: %d\n", mtpparentid);
				mtpmap[mtpparentid] = new Tree();
				MTPD("prevparent addNode\n");
				for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
					node = i->second->findNodePath(parent, i->second->Root());
					if (node != NULL) {
						i->second->setMtpParentId(mtpparentid, node);
					}
				}
				node = mtpmap[mtpparentid]->addNode(mtpid, item);
				node->addProperties(storageID, getParentObject(path));
				if (sendEvents)
					mServer->sendObjectAdded(mtpid);
			}
			else {
				MTPD("add node\n");
				mtpmap[mtpparentid]->addNode(mtpid, item);
				for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
					node = i->second->findNodePath(item, i->second->Root());
					if (node != NULL) {
						i->second->setMtpParentId(mtpparentid, node);
						node->addProperties(storageID, getParentObject(path));
					}
				}
				if (sendEvents)
					mServer->sendObjectAdded(mtpid);
			}
			prevparent = parent;
		}
		else {
			if (strcmp(de->d_name, "..") != 0) {
				// Handle files
				item = path + "/" + de->d_name;
				MTPD("file: %s\n", item.c_str());
				parent = item.substr(0, item.find_last_of('/'));
				MTPD("parent: %s\n", parent.c_str());
				++mtpid;
				MTPD("mtpid: %d\n", mtpid);
				if (prevparent != parent) {
					mtpparentid++;
					MTPD("mtpparentid1: %d\n", mtpparentid);
					for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
						node = i->second->findNodePath(path, i->second->Root());
						if (node != NULL) {
							i->second->setMtpParentId(mtpparentid, node);
							node->addProperties(storageID, getParentObject(path));
						}
					}
				}
				if (mtpmap[mtpparentid] == NULL) {
					mtpmap[mtpparentid] = new Tree();
				}
				MTPD("blank addNode\n");
				node = mtpmap[mtpparentid]->addNode(mtpid, item);
				node->addProperties(storageID, getParentObject(path));
				prevparent = parent;
				if (sendEvents)
					mServer->sendObjectAdded(mtpid);
			}
			else {
				// Handle empty dirs?
				MTPD("checking for empty dir '%s'\n", path.c_str());
				int count = 0;
				DIR *dirc;
				struct dirent *ep;
				dirc = opendir(path.c_str());
				if (dirc != NULL) {
					while ((ep = readdir(dirc)))
						++count;
					MTPD("count: %d\n", count);
					closedir(dirc);
				}
				if (count == 2) {
					MTPD("'%s' is an empty dir\n", path.c_str());
					createEmptyDir(path.c_str());
					goto end;
				}
			}
		}
	}
	end:
		closedir(d);
		return 0;
}

void MtpStorage::deleteTrees(int parent) {
	Node* node = mtpmap[parent]->Root();
	MTPD("MtpStorage::deleteTrees deleting %i\n", parent);
	while (node != NULL) {
		if (node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT) == MTP_FORMAT_ASSOCIATION) {
			deleteTrees(node->getMtpParentId());
		}
		node = mtpmap[parent]->getNext(node);
	}
	delete mtpmap[parent];
	mtpmap.erase(parent);
	MTPD("MtpStorage::deleteTrees deleted %i\n", parent);
}

int MtpStorage::deleteFile(MtpObjectHandle handle) {
	int local_parent_id = 0;
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		MTPD("MtpStorage::deleteFile handle: %d\n", handle);
		Node* node = i->second->findNode(handle, i->second->Root());
		MTPD("MtpStorage::deleteFile node returned: %d\n", node);
		if (node != NULL) {
			if (node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT) == MTP_FORMAT_ASSOCIATION) {
				local_parent_id = node->getMtpParentId();
			}
			MTPD("deleting handle: %d\n", handle);
			i->second->deleteNode(handle);
			MTPD("deleted\n");
			goto end;
		}
	}
	return -1;
end:
	if (local_parent_id) {
		deleteTrees(local_parent_id);
	}
	return 0;
}

int MtpStorage::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
	Node *n;
	int local_mtpid = 0;
	int local_mtpparentid = 0;
	std::vector<int> propertyCodes;
	std::vector<int> dataTypes;
	std::vector<std::string> valueStrs;
	std::vector<int> longValues;
	int count = 0;
	MTPD("MtpStorage::getObjectPropertyList handle: %d, format: %d, property: %lx\n", handle, format, property);
	if (property == MTP_PROPERTY_OBJECT_FORMAT) {
		MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_OBJECT_FORMAT\n");
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node *node = i->second->findNode(handle, i->second->Root());
			MTPD("index: %d\n", index);
			MTPD("node: %d\n", node);
			if (node != NULL) {
				uint64_t longval = node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT);
				local_mtpparentid = i->second->getMtpParentId(node);
				MTPD("object format longValue: %llu\n", longval);
				propertyCodes.push_back(MTP_PROPERTY_OBJECT_FORMAT);
				longValues.push_back(node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT));
				valueStrs.push_back("");
				dataTypes.push_back(4);
				count = 1;
				local_mtpid = node->Mtpid();
				goto endloop;
			}
		}
	}
	else if (property == MTP_PROPERTY_STORAGE_ID) {
		MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_STORAGE_ID\n");
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node *node = i->second->findNode(handle, i->second->Root());
			if (node != NULL) {
				propertyCodes.push_back(MTP_PROPERTY_STORAGE_ID);
				longValues.push_back(getStorageID());
				valueStrs.push_back("");
				dataTypes.push_back(4);
				count = 1;
				local_mtpid = node->Mtpid();
				goto endloop;
			}
		}
	}
	else if (property == MTP_PARENT_ROOT) {
		MTPD("MtpStorage::getObjectPropertyList MTP_PARENT_ROOT\n");
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node* node = i->second->findNode(handle, i->second->Root());
			if (node != NULL) {
				local_mtpparentid = i->second->getMtpParentId(node);
				MTPD("path: %s\n", i->second->getPath(node).c_str());
				MTPD("mtpparentid: %d going to endloop\n", local_mtpparentid);
				std::vector<Node::mtpProperty> mtpprop = node->getMtpProps();
				count = mtpprop.size();
				for (int i = 0; i < count; ++i) {
					propertyCodes.push_back(mtpprop[i].property);
					longValues.push_back(mtpprop[i].valueInt);
					valueStrs.push_back(mtpprop[i].valueStr);
					dataTypes.push_back(mtpprop[i].dataType);
				}
				local_mtpid = node->Mtpid();
				goto endloop;
			}
		}
	}
	else if (property == MTP_PROPERTY_PROTECTION_STATUS) {
		MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_PROTECTION_STATUS\n");
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node *node = i->second->findNode(handle, i->second->Root());
			if (node != NULL) {
				propertyCodes.push_back(MTP_PROPERTY_PROTECTION_STATUS);
				longValues.push_back(0);
				valueStrs.push_back("");
				dataTypes.push_back(8);
				count = 1;
				local_mtpid = node->Mtpid();
				goto endloop;
			}
		}
	}
	else if (property == MTP_PROPERTY_OBJECT_SIZE) {
		MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_OBJECT_SIZE\n");
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node *node = i->second->findNode(handle, i->second->Root());
			if (node != NULL) {
				struct stat st;
				uint64_t size;
				lstat(node->getPath().c_str(), &st);
				size = st.st_size;
				propertyCodes.push_back(MTP_PROPERTY_OBJECT_SIZE);
				longValues.push_back(size);
				valueStrs.push_back("");
				dataTypes.push_back(8);
				count = 1;
				local_mtpid = node->Mtpid();
				goto endloop;
			}
		}
	}
	else {
		// Either the property is not supported or the handle is not on this storage
		return -1;
	}
	// handle not found on this storage
	return -1;

endloop:
	MTPD("mtpparentid: %d\n", local_mtpparentid);
	MTPD("count: %d\n", count);
	packet.putUInt32(count);

	if (count > 0) {
		std::string stringValuesArray;
		for (int i = 0; i < count; ++i) {
			packet.putUInt32(local_mtpid);
			packet.putUInt16(propertyCodes[i]);
			MTPD("dataTypes: %d\n", dataTypes[i]);
			packet.putUInt16(dataTypes[i]);
			MTPD("propertyCode: %s\n", MtpDebug::getObjectPropCodeName(propertyCodes[i]));
			MTPD("longValues: %d\n", longValues[i]);
			switch (dataTypes[i]) {
				case MTP_TYPE_INT8:
					MTPD("MTP_TYPE_INT8\n");
					packet.putInt8(longValues[i]);
					break;
				case MTP_TYPE_UINT8:
					MTPD("MTP_TYPE_UINT8\n");
					packet.putUInt8(longValues[i]);
					break;
				case MTP_TYPE_INT16:
					MTPD("MTP_TYPE_INT16\n");
					packet.putInt16(longValues[i]);
					break;
				case MTP_TYPE_UINT16:
					MTPD("MTP_TYPE_UINT16\n");
					packet.putUInt16(longValues[i]);
					break;
				case MTP_TYPE_INT32:
					MTPD("MTP_TYPE_INT32\n");
					packet.putInt32(longValues[i]);
					break;
				case MTP_TYPE_UINT32:
					MTPD("MTP_TYPE_UINT32\n");
					packet.putUInt32(longValues[i]);
					break;
				case MTP_TYPE_INT64:
					MTPD("MTP_TYPE_INT64\n");
					packet.putInt64(longValues[i]);
					break;
				case MTP_TYPE_UINT64:
					MTPD("MTP_TYPE_UINT64\n");
					packet.putUInt64(longValues[i]);
					break;
				case MTP_TYPE_INT128:
					MTPD("MTP_TYPE_INT128\n");
					packet.putInt128(longValues[i]);
					break;
				case MTP_TYPE_UINT128:
					MTPD("MTP_TYPE_UINT128\n");
					packet.putUInt128(longValues[i]);
					break;
				case MTP_TYPE_STR:
					MTPD("MTP_TYPE_STR: %s\n", valueStrs[i].c_str());
					packet.putString((const char*) valueStrs[i].c_str());
					break;
				default:
					MTPE("bad or unsupported data type: %i in MyMtpDatabase::getObjectPropertyList", dataTypes[i]);
					break;
			}
		}
	}
	return 0;
}

int MtpStorage::renameObject(MtpObjectHandle handle, std::string newName) {
	int index;
	MTPD("MtpStorage::renameObject, handle: %d, new name: '%s'\n", handle, newName.c_str());
	if (handle == MTP_PARENT_ROOT) {
		MTPE("parent == MTP_PARENT_ROOT, cannot rename root\n");
		return -1;
	} else {
		for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
			MTPD("root: %d\n", i->second->Root());
			Node* node = i->second->findNode(handle, i->second->Root());
			if (node != NULL) {
				std::string oldName = i->second->getPath(node);
				std::string parentdir = oldName.substr(0, oldName.find_last_of('/'));
				std::string newFullName = parentdir + "/" + newName;
				MTPD("old: '%s', new: '%s'\n", oldName.c_str(), newFullName.c_str());
				if (rename(oldName.c_str(), newFullName.c_str()) == 0) {
					node->setPath(newFullName);
					return 0;
				} else {
					MTPE("MtpStorage::renameObject failed, handle: %d, new name: '%s'\n", handle, newName.c_str());
					return -1;
				}
			}
		}
	}
	// handle not found on this storage
	return -1;
}

void MtpStorage::createEmptyDir(const char* path) {
	Node *node;
	++mtpparentid;
	MtpStorageID storage = getStorageID();
	MTPD("MtpStorage::createEmptyDir path: '%s', storage: %i, mtpparentid: %d\n", path, storage, mtpparentid);
	mtpmap[mtpparentid] = new Tree();
	for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
		node = i->second->findNodePath(path, i->second->Root());
		if (node != NULL) {
			mtpmap[mtpparentid]->setMtpParentId(mtpparentid, node);
		}
	}
}

int MtpStorage::getObjectPropertyValue(MtpObjectHandle handle, MtpObjectProperty property, uint64_t &longValue) {
	Node *node;
	for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
		node = i->second->findNode(handle, i->second->Root());
		if (node != NULL) {
			longValue = node->getIntProperty(property);
			return 0;
		}
	}
	// handle not found on this storage
	return -1;
}
pthread_t MtpStorage::inotify(void) {
	pthread_t thread;
	ThreadPtr inotifyptr = &MtpStorage::inotify_t;
	PThreadPtr p = *(PThreadPtr*)&inotifyptr;
	pthread_create(&thread, NULL, p, this);
	return thread;
}

int MtpStorage::addInotifyDirs(std::string path) {
	struct dirent *de;
	DIR *d;
	struct stat st;
	std::string inotifypath;

	d = opendir(path.c_str());
	if (d == NULL) {
		MTPE("MtpStorage::addInotifyDirs unable to open '%s'\n", path.c_str());
		closedir(d);
		return -1;
	}

	while ((de = readdir(d)) != NULL) {
		if (de->d_type != DT_DIR || strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
			continue;
		inotifypath = path + "/" + de->d_name;
		if (addInotifyDirs(inotifypath)) {
			closedir(d);
			return -1;
		}
		inotify_wd = inotify_add_watch(inotify_fd, inotifypath.c_str(), IN_CREATE | IN_DELETE);
		inotifymap[inotify_wd] = inotifypath;
		MTPD("added inotify dir: '%s'\n", inotifypath.c_str());
	}
	closedir(d);
	return 0;
}

int MtpStorage::inotify_t(void) {
	int len, i = 0;
	int local_mtpparentid;
	Node* node = NULL;
	struct stat st;
	#define EVENT_SIZE ( sizeof(struct inotify_event) )
	#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16) )
	char buf[EVENT_BUF_LEN];
	std::string item, parent = "";

	MTPD("starting inotify thread\n");
	inotify_fd = inotify_init();

	if (inotify_fd < 0){
		MTPE("Can't run inotify for mtp server\n");
	}

	inotify_wd = inotify_add_watch(inotify_fd, getPath(), WATCH_FLAGS);
	inotifymap[inotify_wd] = getPath();
	if (addInotifyDirs(getPath())) {
		MTPE("MtpStorage::inotify_t failed to add watches to directories\n");
		for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
			inotify_rm_watch(inotify_fd, i->first);
		}
		close(inotify_fd);
		return -1;
	}

	while (true) {
		i = 0;
		len = read(inotify_fd, buf, EVENT_BUF_LEN);

		if (len < 0) {
			MTPE("inotify_t Can't read inotify events\n");
		}

		while (i < len) {
			struct inotify_event *event = ( struct inotify_event * ) &buf[ i ];
			if ( event->len ) {
				if (inotifymap[event->wd].empty()) {
					MTPE("Unable to locate inotify_wd: %i\n", event->wd);
					goto end;
				} else {
					item = inotifymap[event->wd];
					item = item	+ "/" + event->name;
					MTPD("inotify_t item: '%s'\n", item.c_str());
					if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) {
						lockMutex(1);
						if (event->mask & IN_ISDIR) {
							MTPD("inotify_t create is dir\n");
						} else {
							MTPD("inotify_t create is file\n");
						}
						for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
							node = i->second->findNodePath(item, i->second->Root());
							if (node != NULL)
								break;
						}
						if (node == NULL) {
							parent = item.substr(0, item.find_last_of('/'));
							MTPD("parent: %s\n", parent.c_str());
							if (parent == getPath()) {
								local_mtpparentid = 1;
							} else {
								for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
									node = i->second->findNodePath(parent, i->second->Root());
									MTPD("searching for node: %d\n", (int)node);
									if (node != NULL) {
										local_mtpparentid = i->second->getMtpParentId(node);
										break;
									}
								}
								if (node == NULL) {
									MTPE("inotify_t unable to locate mtparentid\n");
									goto end;
								}
							}
							++mtpid;
							MTPD("mtpid: %d\n", mtpid);
							MTPD("mtpparentid1: %d\n", local_mtpparentid);
							node = mtpmap[local_mtpparentid]->addNode(mtpid, item);
							mtpmap[local_mtpparentid]->setMtpParentId(local_mtpparentid, node);
							node->addProperties(getStorageID(), getParentObject(parent));
							if (event->mask & IN_ISDIR) {
								createEmptyDir(item.c_str());
							}
							mServer->sendObjectAdded(mtpid);
						} else {
							MTPD("inotify_t item already exists.\n");
						}
						if (event->mask & IN_ISDIR) {
							inotify_wd = inotify_add_watch(inotify_fd, item.c_str(), WATCH_FLAGS);
							inotifymap[inotify_wd] = item;
							MTPD("added inotify dir: '%s'\n", item.c_str());
							MTPD("inotify_t scanning new dir\n");
							readParentDirs(item);
							std::string mtpParent;
							while (!mtpParentList.empty()) {
								mtpParent = mtpParentList.front();
								mtpParentList.pop_front();
								readParentDirs(mtpParent);
								inotify_wd = inotify_add_watch(inotify_fd, mtpParent.c_str(), WATCH_FLAGS);
								inotifymap[inotify_wd] = mtpParent;
								MTPD("added inotify dir: '%s'\n", mtpParent.c_str());
							}
						}
					} else if (event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) {
						lockMutex(1);
						if (event->mask & IN_ISDIR) {
							MTPD("inotify_t Directory %s deleted\n", event->name);
						} else {
							MTPD("inotify_t File %s deleted\n", event->name);
						}
						for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
							node = i->second->findNodePath(item, i->second->Root());
							if (node != NULL)
								break;
						}
						if (node != NULL && node->Mtpid() > 0) {
							int local_id = node->Mtpid();
							node = NULL;
							deleteFile(local_id);
							mServer->sendObjectRemoved(local_id);
						} else {
							MTPD("inotify_t already removed.\n");
						}
						if (event->mask & IN_ISDIR) {
							std::string orig_item = item + "/";
							size_t item_size = orig_item.size();
							std::string path_check;
							for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
								if ((i->second.size() > item_size && i->second.substr(0, item_size) == orig_item) || i->second == item) {
									inotify_rm_watch(inotify_fd, i->first);
									MTPD("inotify_t removing watch on '%s'\n", i->second.c_str());
									inotifymap.erase(i->first);
								}
							}
						}
					} else if (event->mask & IN_MODIFY) {
						MTPD("inotify_t item %s modified.\n", event->name);
						for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
							node = i->second->findNodePath(item, i->second->Root());
							if (node != NULL)
								break;
						}
						if (node != NULL) {
							uint64_t orig_size = node->getIntProperty(MTP_PROPERTY_OBJECT_SIZE);
							struct stat st;
							lstat(item.c_str(), &st);
							uint64_t new_size = (uint64_t)st.st_size;
							if (orig_size != new_size) {
								MTPD("size changed from %llu to %llu on mtpid: %i\n", orig_size, new_size, node->Mtpid());
								node->updateProperty(MTP_PROPERTY_OBJECT_SIZE, new_size, "", MTP_TYPE_UINT64);
								mServer->sendObjectUpdated(node->Mtpid());
							}
						} else {
							MTPE("inotify_t modified item not found\n");
						}
					}
				}
			}
end:
			unlockMutex(1);
			i += EVENT_SIZE + event->len;
		}
	}

	for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
		inotify_rm_watch(inotify_fd, i->first);
	}
	close(inotify_fd);
	return 0;
}

int MtpStorage::getParentObject(std::string parent_path) {
	Node* node;
	if (parent_path == getPath()) {
		MTPD("MtpStorage::getParentObject for: '%s' returning: 0 for root\n", parent_path.c_str());
		return 0;
	}
	for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
		node = i->second->findNodePath(parent_path, i->second->Root());
		if (node != NULL) {
			MTPD("MtpStorage::getParentObject for: '%s' returning: %i\n", parent_path.c_str(), node->Mtpid());
			return node->Mtpid();
		}
	}
	MTPE("MtpStorage::getParentObject for: '%s' unable to locate node\n", parent_path.c_str());
	return -1;
}

void MtpStorage::lockMutex(int thread_type) {
	if (!use_mutex)
		return; // mutex is disabled
	if (thread_type) {
		// inotify thread
		pthread_mutex_lock(&inMutex);
		while (pthread_mutex_trylock(&mtpMutex)) {
			pthread_mutex_unlock(&inMutex);
			usleep(32000);
			pthread_mutex_lock(&inMutex);
		}
	} else {
		// main mtp thread
		pthread_mutex_lock(&mtpMutex);
		while (pthread_mutex_trylock(&inMutex)) {
			pthread_mutex_unlock(&mtpMutex);
			usleep(13000);
			pthread_mutex_lock(&mtpMutex);
		}
	}
}

void MtpStorage::unlockMutex(int thread_type) {
	if (!use_mutex)
		return; // mutex is disabled
	pthread_mutex_unlock(&inMutex);
	pthread_mutex_unlock(&mtpMutex);
}
