/*
 * 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");
		MTPD("mtpmap count: %d\n", mtpmap.size());
		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;
	}

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 foudn 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);
}
