/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            netcom.cc
 *
 *  Mon Aug 18 09:33:26 CEST 2008
 *  Copyright 2008 Bent Bisballe Nyeng
 *  deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of Pracro.
 *
 *  Pracro is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Pracro 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Pracro; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include "netcom.h"

#include <QtNetwork>

#include <QApplication>
#include <QByteArray>

#include <QHttp>

#include <QWidget>

#include "widgets/widget.h"

#include "debug.h"

#ifdef USE_SSL
#include <QMessageBox>
#include <QList>
#include <QSslError>
#include <QSslSocket>

#ifdef QT_NO_OPENSSL
#error "QT not compiled with SSL support."
#endif
#endif

NetCom::NetCom(QString host, quint16 port)
{
  //
  // Setup connection
  //
  QUrl url;
  url.setHost(host);
  url.setPort(port);
  url.setScheme("http");
  //  url.setScheme("https");

  request.setUrl(url);

  manager = new QNetworkAccessManager(this);
  connect(manager, SIGNAL(finished(QNetworkReply*)),
          this, SLOT(replyFinished(QNetworkReply*)));
}

NetCom::~NetCom()
{
  //
  // Clean up
  //
  delete manager;
}

void NetCom::replyFinished(QNetworkReply *reply)
{
  finished[reply] = true;
}

QDomDocument NetCom::makeTransfer(QDomDocument &doc,
                                  bool commit, bool lockgui, bool discard)
{
  DEBUG(netcom, "Making transfer:\n%s", doc.toString().toStdString().c_str());

  if(lockgui && qApp->activeWindow()) qApp->activeWindow()->setEnabled(false);
  if(lockgui) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

  if(sessionid != "") request.setRawHeader("SessionID",
                                           sessionid.toStdString().c_str());
  if(commit) {
    request.setRawHeader("SessionCommit", "yes");
  }

  if(discard) {
    request.setRawHeader("SessionDiscard", "yes");
  }

  //  QNetworkReply *reply = manager->get(request);
  QNetworkReply *reply = manager->post(request, doc.toByteArray());
  finished[reply] = false;
  while(finished[reply] == false) {
    qApp->processEvents(QEventLoop::WaitForMoreEvents, 100);
  }
  finished.remove(reply);

  QByteArray data = reply->readAll();
  QDomDocument res_doc;
  res_doc.setContent(data);

  DEBUG(netcom, "Recieved reponse:\n%s", data.data());

  DEBUG(netcom, "Recieved reponse (Parsed):\n%s", res_doc.toByteArray().data());

  if(reply->hasRawHeader("SessionID")) {
    sessionid = reply->rawHeader("SessionID");
    LOG(netcom, "SESSION ID: %s\n", sessionid.toStdString().c_str());
  }

  if(lockgui) QApplication::restoreOverrideCursor();
  if(lockgui && qApp->activeWindow()) qApp->activeWindow()->setEnabled(true);

  return res_doc;
}

QDomDocument NetCom::initConnection()
{
  QDomDocument doc;
  return makeTransfer(doc, false, true);
}

QDomDocument NetCom::commit()
{
  QDomDocument doc;
  return makeTransfer(doc, true, true);
}

QDomDocument NetCom::discard()
{
  QDomDocument doc;
  return makeTransfer(doc, false, true, true);
}

QDomDocument NetCom::send(QString templ, QString macro, bool lockgui)
{
  QDomDocument doc;

  QDomProcessingInstruction header =
    doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
  doc.appendChild(header); 

  QDomElement pracro_elem = doc.createElement("pracro");
  pracro_elem.setAttribute("version", "1.0");
  pracro_elem.setAttribute("cpr", patientid);
  pracro_elem.setAttribute("user", user);
  doc.appendChild(pracro_elem);

  QDomElement request_elem = doc.createElement("request");
  request_elem.setAttribute("template", templ);
  if(macro != "") request_elem.setAttribute("macro", macro);
  pracro_elem.appendChild(request_elem);

  return makeTransfer(doc, false, lockgui);
}

QDomDocument NetCom::send(QVector< Widget* > widgets, QString templ,
                          QString macro, QString version)
{
  QDomDocument doc;

  QDomProcessingInstruction header =
    doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
  doc.appendChild(header); 

  QDomElement pracro_elem = doc.createElement("pracro");
  pracro_elem.setAttribute("version", "1.0");
  pracro_elem.setAttribute("cpr", patientid);
  pracro_elem.setAttribute("user", user);
  doc.appendChild(pracro_elem);

  QDomElement commit_elem = doc.createElement("commit");
  commit_elem.setAttribute("template", templ);
  commit_elem.setAttribute("macro", macro);
  commit_elem.setAttribute("version", version);
  pracro_elem.appendChild(commit_elem);

  // Iterate the different entries, and append their results to
  //  the commit string
  QVector< Widget* >::iterator i = widgets.begin();
  while(i != widgets.end()) {
    DEBUG(netcom, "W = ");
    if(*i) {
      Widget* w = *i;
      DEBUG(netcom, "name: %s val: %s", w->name().toStdString().c_str(),
            w->value().toStdString().c_str());
      if(w->enabled() && w->name() != "" && w->local() == false) {
        QDomElement field_elem = doc.createElement("field");
        field_elem.setAttribute("name", w->name());
        field_elem.setAttribute("value", w->value());
        commit_elem.appendChild(field_elem);
      }
    }
    i++;
  }
  
  return makeTransfer(doc, false, true);
}