/*!
    \qmlmethod bool FacebookPhoto::untagText(const QString &text)
    Initiates a "delete tag" operation on the tag specified by
    the given text.

    If the network request was started successfully, the function
    will return true and the status of the photo will change to
    \c SocialNetwork::Busy.  Otherwise, the function will return
    false.
*/
bool FacebookPhotoInterface::untagText(const QString &text)
{
    QVariantMap extraData;
    extraData.insert("tag_text", text);

    // try to find which tag will be removed if it succeeds
    int tempPendingTagToRemoveIndex = -1;
    for (int i = 0; i < f->tags.count(); ++i) {
        QString tagText = f->tags.at(i)->text();
        if (!tagText.isEmpty() && tagText == text) {
            tempPendingTagToRemoveIndex = i;
            break;
        }
    }

    // possible that it's ok to not exist, since we might be out of sync with reality.
    if (tempPendingTagToRemoveIndex == -1)
        qWarning() << Q_FUNC_INFO << "Unknown tag specified for removal";

    bool requestMade = request(IdentifiableContentItemInterface::Delete,
                               identifier(), QLatin1String("tags"),
                               QStringList(), QVariantMap(), extraData);

    if (!requestMade)
        return false;

    f->action = FacebookInterfacePrivate::DeleteTagAction;
    f->pendingTagToRemoveIndex = tempPendingTagToRemoveIndex;
    connect(f->dd->reply(), SIGNAL(finished()), f, SLOT(finishedHandler()));
    connect(f->dd->reply(), SIGNAL(error(QNetworkReply::NetworkError)), f->dd, SLOT(defaultErrorHandler(QNetworkReply::NetworkError)));
    connect(f->dd->reply(), SIGNAL(sslErrors(QList<QSslError>)), f->dd, SLOT(defaultSslErrorsHandler(QList<QSslError>)));
    return true;
}
bool ArbitraryRequestHandler::request(int requestType, const QString &requestUri, const QVariantMap &queryItems, const QString &postData)
{
    if (reply) {
        qWarning() << Q_FUNC_INFO << "Warning: cannot start arbitrary request: another arbitrary request is in progress";
        return false;
    }

    QList<QPair<QString, QString> > qil;
    QStringList queryItemKeys = queryItems.keys();
    foreach (const QString &qik, queryItemKeys)
        qil.append(qMakePair<QString, QString>(qik, queryItems.value(qik).toString()));

    QUrl url(requestUri);
    url.setQueryItems(qil);

    QNetworkReply *sniReply = 0;
    switch (requestType) {
        case SocialNetworkInterface::Get: sniReply = q->d->qnam->get(QNetworkRequest(url)); break;
        case SocialNetworkInterface::Post: sniReply = q->d->qnam->post(QNetworkRequest(url), QByteArray::fromBase64(postData.toLatin1())); break;
        default: sniReply = q->d->qnam->deleteResource(QNetworkRequest(url)); break;
    }

    if (sniReply) {
        reply = sniReply;
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
        connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
        connect(reply, SIGNAL(finished()), this, SLOT(finishedHandler()));
        return true;
    }

    qWarning() << Q_FUNC_INFO << "Warning: cannot start arbitrary request: null reply";
    return false;
}
/*!
    \qmlmethod bool FacebookPhoto::removeComment(const QString &identifier)
    Initiates a "delete comment" operation on the comment specified by
    the given \a identifier.

    If the network request was started successfully, the function
    will return true and the status of the photo will change to
    \c SocialNetwork::Busy.  Otherwise, the function will return
    false.
*/
bool FacebookPhotoInterface::removeComment(const QString &commentIdentifier)
{
    bool requestMade = request(IdentifiableContentItemInterface::Delete, commentIdentifier);

    if (!requestMade)
        return false;

    f->action = FacebookInterfacePrivate::DeleteCommentAction;
    connect(f->dd->reply(), SIGNAL(finished()), f, SLOT(finishedHandler()));
    connect(f->dd->reply(), SIGNAL(error(QNetworkReply::NetworkError)), f->dd, SLOT(defaultErrorHandler(QNetworkReply::NetworkError)));
    connect(f->dd->reply(), SIGNAL(sslErrors(QList<QSslError>)), f->dd, SLOT(defaultSslErrorsHandler(QList<QSslError>)));
    return true;
}
/*!
    \qmlmethod bool FacebookPhoto::unlike()
    Initiates a "delete like" operation on the photo.

    If the network request was started successfully, the function
    will return true and the status of the photo will change to
    \c SocialNetwork::Busy.  Otherwise, the function will return
    false.
*/
bool FacebookPhotoInterface::unlike()
{
    bool requestMade = request(IdentifiableContentItemInterface::Delete,
                               identifier(), QLatin1String("likes"));

    if (!requestMade)
        return false;

    f->action = FacebookInterfacePrivate::DeleteLikeAction;
    connect(f->dd->reply(), SIGNAL(finished()), f, SLOT(finishedHandler()));
    connect(f->dd->reply(), SIGNAL(error(QNetworkReply::NetworkError)), f->dd, SLOT(defaultErrorHandler(QNetworkReply::NetworkError)));
    connect(f->dd->reply(), SIGNAL(sslErrors(QList<QSslError>)), f->dd, SLOT(defaultSslErrorsHandler(QList<QSslError>)));
    return true;
}
/*!
    \qmlmethod bool FacebookPhoto::uploadComment(const QString &message)
    Initiates a "post comment" operation on the photo.  The comment
    will contain the specified \a message.

    If the network request was started successfully, the function
    will return true and the status of the photo will change to
    \c SocialNetwork::Busy.  Otherwise, the function will return
    false.

    Once the network request completes, the \c responseReceived()
    signal will be emitted.  The \c data parameter of the signal
    will contain the \c id of the newly uploaded comment.
*/
bool FacebookPhotoInterface::uploadComment(const QString &message)
{
    QVariantMap postData;
    postData.insert("message", message);

    bool requestMade = request(IdentifiableContentItemInterface::Post,
                               identifier(), QLatin1String("comments"),
                               QStringList(), postData);

    if (!requestMade)
        return false;

    f->action = FacebookInterfacePrivate::UploadCommentAction;
    connect(f->dd->reply(), SIGNAL(finished()), f, SLOT(finishedHandler()));
    connect(f->dd->reply(), SIGNAL(error(QNetworkReply::NetworkError)), f->dd, SLOT(defaultErrorHandler(QNetworkReply::NetworkError)));
    connect(f->dd->reply(), SIGNAL(sslErrors(QList<QSslError>)), f->dd, SLOT(defaultSslErrorsHandler(QList<QSslError>)));
    return true;
}
/*!
    \qmlmethod bool FacebookPhoto::tagText(const QString &text, qreal xOffset, qreal yOffset)
    Initiates a "tag text" operation on the photo.  The position
    specified by the given \a xOffset and \a yOffset will be tagged
    with the specified \a text.

    If the network request was started successfully, the function
    will return true and the status of the photo will change to
    \c SocialNetwork::Busy.  Otherwise, the function will return
    false.

    Once the network request completes, the \c responseReceived()
    signal will be emitted.
*/
bool FacebookPhotoInterface::tagText(const QString &text, qreal xOffset, qreal yOffset)
{
    QVariantMap postData;
    postData.insert("tag_text", text);
    if (xOffset != -1)
        postData.insert("x", QString::number(xOffset));
    if (yOffset != -1)
        postData.insert("y", QString::number(yOffset));

    bool requestMade = request(IdentifiableContentItemInterface::Post,
                               identifier(), QLatin1String("tags"),
                               QStringList(), postData);

    if (!requestMade)
        return false;

    f->action = FacebookInterfacePrivate::TagAction;
    connect(f->dd->reply(), SIGNAL(finished()), f, SLOT(finishedHandler()));
    connect(f->dd->reply(), SIGNAL(error(QNetworkReply::NetworkError)), f->dd, SLOT(defaultErrorHandler(QNetworkReply::NetworkError)));
    connect(f->dd->reply(), SIGNAL(sslErrors(QList<QSslError>)), f->dd, SLOT(defaultSslErrorsHandler(QList<QSslError>)));
    return true;
}
void IdentifiableContentItemInterfacePrivate::connectFinishedAndErrors()
{
    Q_Q(IdentifiableContentItemInterface);
    QObject::connect(reply(), SIGNAL(finished()), q, SLOT(finishedHandler()));
    connectErrors();
}