/*! @file

    @id $Id$
*/
//       1         2         3         4         5         6         7         8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#ifndef __NETWORKACCESS_MANAGER_HXX__
#define __NETWORKACCESS_MANAGER_HXX__

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkConfiguration>
#include <QNetworkProxy>

class NetworkAccessManager: public QNetworkAccessManager {
    Q_OBJECT;
  public:
    NetworkAccessManager(QObject* parent = 0): QNetworkAccessManager(parent) {
      //log(__PRETTY_FUNCTION__);
      connect(this,
              SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
              SLOT(authenticationRequiredLog(QNetworkReply*, QAuthenticator*)));
      connect(this,
              SIGNAL(encrypted(QNetworkReply*)),
              SLOT(encryptedLog(QNetworkReply*)));
      connect(this,
              SIGNAL(finished(QNetworkReply*)),
              SLOT(finishedLog(QNetworkReply*)));
      connect(this,
              SIGNAL(networkAccessibleChanged
                     (QNetworkAccessManager::NetworkAccessibility)),
              SLOT(networkAccessibleChangedLog
                   (QNetworkAccessManager::NetworkAccessibility)));
      connect(this,
              SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&,
                                                 QAuthenticator*)),
              SLOT(proxyAuthenticationRequiredLog(const QNetworkProxy&,
                                                  QAuthenticator*)));
      connect(this,
              SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
              SLOT(sslErrorsLog(QNetworkReply*, const QList<QSslError>&)));
    }
    virtual ~NetworkAccessManager() {
      //log(__PRETTY_FUNCTION__);
    }
    QNetworkConfiguration activeConfiguration() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::activeConfiguration();
    }
    QAbstractNetworkCache* cache() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::cache();
    }
    void clearAccessCache() {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::clearAccessCache();
    }
    QNetworkConfiguration configuration() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::configuration();
    }
    void connectToHost(const QString& hostName, quint16 port = 80) {
      //log(__PRETTY_FUNCTION__ + QString(" -> ") + hostName);
      QNetworkAccessManager::connectToHost(hostName, port);
    }
    void connectToHostEncrypted(const QString& hostName, quint16 port = 443,
                                const QSslConfiguration& sslConfiguration
                                = QSslConfiguration::defaultConfiguration()) {
      //log(__PRETTY_FUNCTION__ + QString(" -> ") + hostName);
      QNetworkAccessManager::connectToHostEncrypted(hostName, port,
                                                    sslConfiguration);
    }
    QNetworkCookieJar* cookieJar() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::cookieJar();
    }
    QNetworkReply* deleteResource(const QNetworkRequest & request) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::deleteResource(request);
    }
    QNetworkReply* get(const QNetworkRequest& request) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::get(request);
    }
    QNetworkReply* head(const QNetworkRequest& request) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::head(request);
    }
    NetworkAccessibility networkAccessible() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::networkAccessible();
    }
    QNetworkReply* post(const QNetworkRequest & request, QIODevice * data) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::post(request, data);
    }
    QNetworkReply* post(const QNetworkRequest& request,
                        const QByteArray& data) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::post(request, data);
    }
    QNetworkReply* post(const QNetworkRequest& request,
                        QHttpMultiPart* multiPart) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::post(request, multiPart);
    }
    QNetworkProxy proxy() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::proxy();
    }
    QNetworkProxyFactory* proxyFactory() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::proxyFactory();
    }
    QNetworkReply* put(const QNetworkRequest& request, QIODevice* data) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::put(request, data);
    }
    QNetworkReply* put(const QNetworkRequest& request,
                       QHttpMultiPart* multiPart) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::put(request, multiPart);
    }
    QNetworkReply* put(const QNetworkRequest& request, const QByteArray& data) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::put(request, data);
    }
    QNetworkReply* sendCustomRequest(const QNetworkRequest& request,
                                     const QByteArray& verb,
                                     QIODevice* data = 0) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::sendCustomRequest(request, verb, data);
    }
    void setCache(QAbstractNetworkCache* cache) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setCache(cache);
    }
    void setConfiguration(const QNetworkConfiguration& config) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setConfiguration(config);
    }
    void setCookieJar(QNetworkCookieJar* cookieJar) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setCookieJar(cookieJar);
    }
    void setNetworkAccessible(NetworkAccessibility accessible) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setNetworkAccessible(accessible);
    }
    void setProxy(const QNetworkProxy& proxy) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setProxy(proxy);
    }
    void setProxyFactory(QNetworkProxyFactory* factory) {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::setProxyFactory(factory);
    }
    QStringList supportedSchemes() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::supportedSchemes();
    }
  Q_SIGNALS:
    void authenticationRequired(QNetworkReply*, QAuthenticator*);
    void encrypted(QNetworkReply*);
    void finished(QNetworkReply*);
    void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility);
    void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*);
    void sslErrors(QNetworkReply*, const QList<QSslError>&);
    void log(QString) const;
  protected:
    virtual QNetworkReply* createRequest(Operation op,
                                         const QNetworkRequest& req,
                                         QIODevice* outgoingData = 0) {
      //log(__PRETTY_FUNCTION__ + QString(" -> ") + req.url().url());
      switch (op) {
        case QNetworkAccessManager::HeadOperation: break;
        case QNetworkAccessManager::GetOperation: break;
        case QNetworkAccessManager::PutOperation: break;
        case QNetworkAccessManager::PostOperation: break;
        case QNetworkAccessManager::DeleteOperation: break;
        case QNetworkAccessManager::CustomOperation: break;
        case QNetworkAccessManager::UnknownOperation: break;
      }
      QNetworkReply* reply
        (QNetworkAccessManager::createRequest(op, req, outgoingData));
      connect(reply, SIGNAL(encrypted()), SLOT(encryptedLog()));
      connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
              SLOT(errorLog(QNetworkReply::NetworkError)));
      connect(reply, SIGNAL(finished()), SLOT(finishedLog()));
      connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)),
              SLOT(sslErrorsLog(const QList<QSslError>&)));
      return reply;
    }
  protected Q_SLOTS:
    QStringList supportedSchemesImplementation() const {
      //log(__PRETTY_FUNCTION__);
      return QNetworkAccessManager::supportedSchemesImplementation();
    }
  private Q_SLOTS:
    void errorLog(QNetworkReply::NetworkError) {
      log("**** Network Error: "
          + dynamic_cast<QNetworkReply*>(sender())->errorString());
    }
    void authenticationRequiredLog(QNetworkReply*, QAuthenticator*) {
      //log(__PRETTY_FUNCTION__);
    }
    void encryptedLog() {
      //log(__PRETTY_FUNCTION__);
    }
    void encryptedLog(QNetworkReply*) {
      //log(__PRETTY_FUNCTION__);
    }
    void finishedLog() {
      //log(__PRETTY_FUNCTION__);
    }
    void finishedLog(QNetworkReply*) {
      //log(__PRETTY_FUNCTION__);
    }
    void networkAccessibleChangedLog
        (QNetworkAccessManager::NetworkAccessibility) {
      //log(__PRETTY_FUNCTION__);
    }
    void proxyAuthenticationRequiredLog(const QNetworkProxy&, QAuthenticator*) {
      //log(__PRETTY_FUNCTION__);
    }
    void sslErrorsLog(const QList<QSslError>& errors) {
      Q_FOREACH(const QSslError& error, errors) {
        log("**** SSL-Error: "+error.errorString());
      }
      QNetworkReply* reply(dynamic_cast<QNetworkReply*>(QObject::sender()));
      log("#### Ignoring SSL Errors 1");
      reply->ignoreSslErrors();
    }
    void sslErrorsLog(QNetworkReply* reply, const QList<QSslError>&) {
      log("#### Ignoring SSL Errors 2");
      reply->ignoreSslErrors();
    }
};

#endif
