string SearchManager::getPartsString(const PartsInfo& partsInfo) const {
        string ret;

        for(PartsInfo::const_iterator i = partsInfo.begin(); i < partsInfo.end(); i+=2){
                ret += Util::toString(*i) + "," + Util::toString(*(i+1)) + ",";
        }

        return ret.substr(0, ret.size()-1);
}
void QueueItem::getPartialInfo(PartsInfo& partialInfo, int64_t blockSize) const {
	size_t maxSize = min(done.size() * 2, (size_t)510);
	partialInfo.reserve(maxSize);

	SegmentConstIter i = done.begin();
	for(; i != done.end() && partialInfo.size() < maxSize; i++) {

		uint16_t s = (uint16_t)((*i).getStart() / blockSize);
		uint16_t e = (uint16_t)(((*i).getEnd() - 1) / blockSize + 1);

		partialInfo.push_back(s);
		partialInfo.push_back(e);
	}
}
bool QueueItem::isNeededPart(const PartsInfo& partsInfo, int64_t blockSize)
{
	dcassert(partsInfo.size() % 2 == 0);
	
	SegmentConstIter i  = done.begin();
	for(PartsInfo::const_iterator j = partsInfo.begin(); j != partsInfo.end(); j+=2){
		while(i != done.end() && (*i).getEnd() <= (*j) * blockSize)
			i++;

		if(i == done.end() || !((*i).getStart() <= (*j) * blockSize && (*i).getEnd() >= (*(j+1)) * blockSize))
			return true;
	}
	
	return false;

}
void SearchManager::onPSR(const AdcCommand& cmd, UserPtr from, const string& remoteIp) {

        uint16_t udpPort = 0;
        uint32_t partialCount = 0;
        string tth;
        string hubIpPort;
        string nick;
        PartsInfo partialInfo;

        for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) {
                const string& str = *i;
                if(str.compare(0, 2, "U4") == 0) {
                        udpPort = static_cast<uint16_t>(Util::toInt(str.substr(2)));
                } else if(str.compare(0, 2, "NI") == 0) {
                        nick = str.substr(2);
                } else if(str.compare(0, 2, "HI") == 0) {
                        hubIpPort = str.substr(2);
                } else if(str.compare(0, 2, "TR") == 0) {
                        tth = str.substr(2);
                } else if(str.compare(0, 2, "PC") == 0) {
                        partialCount = Util::toUInt32(str.substr(2))*2;
                } else if(str.compare(0, 2, "PI") == 0) {
                        StringTokenizer<string> tok(str.substr(2), ',');
                        for(StringIter i = tok.getTokens().begin(); i != tok.getTokens().end(); ++i) {
                                partialInfo.push_back((uint16_t)Util::toInt(*i));
                        }
                }
        }

        string url = ClientManager::getInstance()->findHub(hubIpPort);
        if(!from || from == ClientManager::getInstance()->getMe()) {
                // for NMDC support

                if(nick.empty() || hubIpPort.empty()) {
                        return;
                }

                from = ClientManager::getInstance()->findUser(nick, url);
                if(!from) {
                        // Could happen if hub has multiple URLs / IPs
                        from = ClientManager::getInstance()->findLegacyUser(nick);
                        if(!from) {
                                dcdebug("Search result from unknown user");
                                return;
                        }
                }
        }

        //ClientManager::getInstance()->setIPUser(from, remoteIp, udpPort);

        if(partialInfo.size() != partialCount) {
                // what to do now ? just ignore partial search result :-/
                return;
        }

        PartsInfo outPartialInfo;
        QueueItem::PartialSource ps(from->isNMDC() ? ClientManager::getInstance()->getClient(url)->getMyIdentity().getNick() : Util::emptyString, hubIpPort, remoteIp, udpPort);
        ps.setPartialInfo(partialInfo);

        QueueManager::getInstance()->handlePartialResult(from, url, TTHValue(tth), ps, outPartialInfo);

        if((udpPort > 0) && !outPartialInfo.empty()) {
                try {
                        AdcCommand cmd = SearchManager::getInstance()->toPSR(false, ps.getMyNick(), hubIpPort, tth, outPartialInfo);
                        ClientManager::getInstance()->send(cmd, from->getCID());
                } catch(...) {
                        dcdebug("Partial search caught error\n");
                }
        }

}