/***************************************************************************
**
**  This file is part of QGpGuiTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2010-12-07
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QtNetwork>

#include <QGpCoreTools.h>

#include "HttpAccess.h"
#include "HttpProxyList.h"

namespace QGpGuiTools {

  /*!
    \class HttpAccess HttpAccess.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  HttpAccess::HttpAccess(const QString& testUrl, QObject * parent)
    : QObject(parent)
  {
    TRACE;
    _proxy=nullptr;
    _proxies=new HttpProxyList(testUrl, this);
    connect(_proxies, SIGNAL(ready()), this, SLOT(testProxies()));
    _proxies->collect();
  }

  /*!
    Description of destructor still missing
  */
  HttpAccess::~HttpAccess()
  {
    TRACE;
    delete _proxy;
  }

  bool HttpAccess::isAvailable()
  {
    TRACE;
    // With Qt 5.5.1, if there is no connection available get() generates a lot of warnings
    QNetworkConfigurationManager con;
    return !con.allConfigurations(QNetworkConfiguration::Discovered).isEmpty() ||
           !con.allConfigurations(QNetworkConfiguration::Active).isEmpty();
  }

  void HttpAccess::get(const QUrl& url)
  {
    TRACE;
    QNetworkAccessManager * manager=new QNetworkAccessManager(this);
    if(_proxy) {
      manager->setProxy(*_proxy);
    }
    QNetworkRequest req(url);
    QNetworkReply * reply=manager->get(req);
    connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
  }

  void HttpAccess::post(const QUrl& url, const QByteArray& data)
  {
    TRACE;
    QNetworkAccessManager * manager=new QNetworkAccessManager(this);
    if(_proxy) {
      manager->setProxy(*_proxy);
    }
    QNetworkRequest req(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    QNetworkReply * reply=manager->post(req, data);
    connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
  }

  void HttpAccess::requestFinished()
  {
    TRACE;
    QNetworkReply * reply=static_cast<QNetworkReply *>(sender());
    if(reply->error()==QNetworkReply::NoError) {
      _receivedData=reply->readAll();
      reply->manager()->deleteLater();
      emit finished(true);
    }
  }

  void HttpAccess::testProxies()
  {
    TRACE;
    for(int i=0; i<_proxies->count(); i++) {
      QNetworkAccessManager * manager=new QNetworkAccessManager(this);
      manager->setProxy(_proxies->at(i).proxy());
      //App::log(QString("Manager: %1").arg(reinterpret_cast<qint64>(manager), 0, 16) << endl;
      //App::log("Testing proxy: " << manager->proxy().hostName() << endl;
      QNetworkReply * reply;
      reply=manager->get(QNetworkRequest(_proxies->testUrl()));
      connect(reply, SIGNAL(finished()), this, SLOT(testFinished()));
      _testReplies.append(reply);
    }
  }


  void HttpAccess::testFinished()
  {
    TRACE;
    if(_testReplies.isEmpty()) { // Already found a good proxy
      return;
    }
    QNetworkReply * reply=static_cast<QNetworkReply *>(sender());
    int index=_testReplies.indexOf(reply);
    if(reply->error()==QNetworkReply::NoError && reply->readAll()=="ACCESS OK\n") {
      if(_proxies->atHome()) {
        _proxy=new QNetworkProxy(QNetworkProxy::HttpProxy, "www-cache.ujf-grenoble.fr", 3128);
      } else {
        _proxy=new QNetworkProxy(reply->manager()->proxy());
      }
      //App::log(QString("Reply manager: %1").arg(reinterpret_cast<qint64>(reply->manager()), 0, 16) << endl;
      //App::log("Detected proxy: " << _proxy->hostName() << endl;
      delete _proxies;
      _proxies=nullptr;
      _testReplies.clear();
      emit ready();
    } else {
      if(index>-1) {
        _testReplies.removeAt(index);
      }
      if(_testReplies.isEmpty()) { // Unfortunately no http access
        emit ready();
      }
    }
    reply->manager()->deleteLater();
  }

} // namespace QGpGuiTools
