/* -*- 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(QWidget *wdg, QString host, quint16 port)
{
  this->wdg = wdg;

  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()
{
  delete manager;
}

void NetCom::replyFinished(QNetworkReply *reply)
{
  if(reply->error() == QNetworkReply::NoError) {
    if(reply->hasRawHeader("SessionID")) {
      sessionid = reply->rawHeader("SessionID");
      LOG(netcom, "Reply SESSION ID: %s\n", sessionid.toStdString().c_str());
    }

    QDomDocument doc;
    doc.setContent(reply->readAll());
    emit gotReply(doc);

  } else {
    emit networkError("Network Error", reply->errorString());
  }
}

void NetCom::makeTransfer(QDomDocument &doc, session_state_t state)
{
  DEBUG(netcom, "Making transfer:\n%s", doc.toString().toStdString().c_str());

  LOG(netcom, "SESSION ID: %s\n", sessionid.toStdString().c_str());

  request.setRawHeader("User-Agent", "Pracro Client v"VERSION);

  if(sessionid != "") {
    request.setRawHeader("SessionID", sessionid.toStdString().c_str());
  } else {
    request.setRawHeader("SessionPatientID", patientid.toStdString().c_str());
    request.setRawHeader("SessionTemplate", templ.toStdString().c_str());
  }

  switch(state) {
  case ::commit:
    request.setRawHeader("SessionCommit", "yes");
    break;
  case ::discard:
    request.setRawHeader("SessionDiscard", "yes");
    break;
  case ::nocommit:
    request.setRawHeader("SessionNoCommit", "yes");
    break;
  default:
  case ::none:
    break;
  }

  manager->post(request, doc.toByteArray());
}

void NetCom::initConnection()
{
  send(templ); // Initialise by sending a template-only request.
}

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

void NetCom::nocommit()
{
  QDomDocument doc;
  makeTransfer(doc, ::nocommit);
}

void NetCom::discard()
{
  QDomDocument doc;
  makeTransfer(doc, ::discard);
}

void NetCom::send(QString templ, QString macro)
{
  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);

  makeTransfer(doc);
}

void 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++;
  }

  QDomElement request_elem = doc.createElement("request");
  request_elem.setAttribute("template", templ);
  pracro_elem.appendChild(request_elem);
  
  makeTransfer(doc);
}