/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <QApplication>
#include <QBuffer>
#include <QDateTime>
#include <QDebug>
#include <QDomDocument>
#include <QFile>
#include <QImage>
#include <QUrl>

#include <QAuthenticator>
#include <QNetworkReply>
#include <QXmlFormatter>
#include <QXmlResultItems>

#include "MvQNetworkAccessManager.h"
#include "MvQOgcRequest.h"
#include "MvQXmlQuery.h"

#include "MvQWmsClient.h"

#include "LogHandler.h"
#include "StatusMsgHandler.h"

#include "mars.h"
#include "Metview.h"

//==============================
//
// MvQProjInfo
//
//==============================

MvQProjInfo::MvQProjInfo(const MvRequest& inReq)
{
    if (strcmp(inReq.getVerb(), "GEOVIEW") != 0)
        return;

    const char* info = inReq("_ZOOM_DEFINITION");
    if (info) {
        parseProj4String(info);
    }
    else {
        parseRequest(inReq);
    }
}


void MvQProjInfo::parseProj4String(const char* info)
{
    if (!info)
        return;

    QString str(info);
    str.remove("\"");
    str.remove("{");
    str.remove("}");

    QMap<QString, QString> param;
    foreach (QString s, str.split(",")) {
        QStringList s1 = s.split(":");
        if (s1.count() == 2) {
            insert(s1[0].simplified(), s1[1].simplified());
        }
    }

    if (value("subpage_map_projection") == "cylindrical") {
        if (value("subpage_map_area_definition") == "full") {
            insert("subpage_lower_left_latitude", "-90");
            insert("subpage_lower_left_longitude", "-180");
            insert("subpage_upper_right_latitude", "90");
            insert("subpage_upper_right_longitude", "180");
        }
    }
}

void MvQProjInfo::parseRequest(const MvRequest& inReq)
{
    MvRequest ctx;

    //Expand the request
    char* shareDir = getenv("METVIEW_DIR_SHARE");
    if (shareDir) {
        string path(shareDir);
        path.append("/etc/");

        string defFileName   = path + "GeoViewDef";
        string rulesFileName = path + "GeoViewRules";

        MvLanguage langMetview(defFileName.c_str(),
                               rulesFileName.c_str(),
                               EXPAND_DEFAULTS);

        ctx = langMetview.expandOne(inReq);
    }
    else {
        ctx = inReq;
    }

    const char* proj = (const char*)ctx("MAP_PROJECTION");

    if (proj && strcmp(proj, "CYLINDRICAL") == 0) {
        insert("subpage_map_projection", "cylindrical");

        const char* ad = (const char*)ctx("MAP_AREA_DEFINITION");
        QString areaDef;
        if (ad) {
            areaDef = QString(ad);
            areaDef = areaDef.toLower();
            insert("subpage_map_area_definition", areaDef);
        }
        else
            return;

        if (areaDef == "corners" && ctx.countValues("AREA") == 4) {
            double dval;
            ctx.getValue(dval, "AREA", 0);
            insert("subpage_lower_left_latitude", QString::number(dval));
            ctx.getValue(dval, "AREA", 1);
            insert("subpage_lower_left_longitude", QString::number(dval));
            ctx.getValue(dval, "AREA", 2);
            insert("subpage_upper_right_latitude", QString::number(dval));
            ctx.getValue(dval, "AREA", 3);
            insert("subpage_upper_right_longitude", QString::number(dval));
        }

        else if (areaDef == "full") {
            insert("subpage_lower_left_latitude", "-90");
            insert("subpage_lower_left_longitude", "-180");
            insert("subpage_upper_right_latitude", "90");
            insert("subpage_upper_right_longitude", "180");
        }
    }
}

QString MvQProjInfo::get(QString key)
{
    QMap<QString, QString>::const_iterator it = find(key);
    if (it != end())
        return it.value();

    else
        return QString();
}


//==============================
//
// Message handler for XQuery
//
//==============================


void MvQWmsMessageHandler::handleMessage(QtMsgType type, const QString& description, const QUrl& /*identifier*/,
                                         const QSourceLocation& /*sourceLocation*/)
{
    if (type == QtFatalMsg) {
        fatalMsg_ << description;
    }
}


//==============================
//
// Base client
//
//==============================

MvQWmsClientBase::MvQWmsClientBase()
{
    supportedMimeType_ << "image/png"
                       << "image/jpeg"
                       << "image/gif";  // "image/svg+xml";

    supportedCrs_ << "EPSG:4326"
                  << "CRS:84";

    queryMsgHandler_ = new MvQWmsMessageHandler;
}

MvQWmsClientBase::~MvQWmsClientBase()
{
    delete queryMsgHandler_;
}

QString MvQWmsClientBase::getMimeType(QByteArray ba)
{
    if (ba.mid(0, 8).toHex() == "89504e470d0a1a0a") {
        return "image/png";
    }
    else if (ba.mid(0, 4).toHex() == "ffd8ffe0") {
        return "image/jpeg";
    }
    else if (ba.mid(0, 6) == "GIF87a" ||
             ba.mid(0, 6) == "GIF89a") {
        return "image/gif";
    }

    return QString("text/plain");
}


QString MvQWmsClientBase::getRequestedMimeType(QString r)
{
    MvQGetMapRequest req;
    req.setRequest(r);
    return req.item("FORMAT");
}

//==============================
//
// Download/batch client
//
//==============================

MvQWmsGetClient::MvQWmsGetClient(MvRequest& req) :
    reqInfo_(req)
{
    //Init
    getMapRunStatus_ = false;
    requestChanged_  = false;

    networkGetMap_ = 0;
    networkLegend_ = 0;
    networkLogo_   = 0;
    getMapReply_   = 0;
    legendReply_   = 0;
    logoReply_     = 0;

    getMapFrameNum_        = 0;
    getMapFrameToDownload_ = -1;

    //Mode
    const char* modec = (const char*)reqInfo_("_ACTION");
    QString mode;
    if (modec)
        mode = QString(modec);

    //Nosubsets
    const char* noSubsets = (const char*)reqInfo_("LAYER_NOSUBSETS");

    //Time dimensions
    QStringList timeDimName;
    const char* tdn = (const char*)reqInfo_("TIME_DIMENSIONS");
    if (tdn) {
        QString s(tdn);
        timeDimName = s.split("/");
    }

    //Create and initialise request object
    getMapRequest_ = new MvQGetMapRequest;
    getMapRequest_->setRequest(QString((const char*)reqInfo_("REQUEST")), timeDimName);

    //Update bbox if needed
    if ((mode == "prepare" || mode == "update") &&
        (noSubsets == 0 || strcmp(noSubsets, "0") == 0)) {
        requestChanged_ = updateBoundingBox();
    }

    //In update mode if bbox was not updated we quit
    if (mode == "update" && requestChanged_ == false) {
        return;
    }

    //Legend and log path
    const char* legend = (const char*)reqInfo_("LAYER_LEGEND");
    if (legend)
        legendPath_ = QString(legend);

    const char* logo = (const char*)reqInfo_("LAYER_LOGO");
    if (logo)
        logoPath_ = QString(logo);


    //Network access
    networkGetMap_ = new MvQNetworkAccessManager(this);
    networkLegend_ = new MvQNetworkAccessManager(this);
    networkLogo_   = new MvQNetworkAccessManager(this);

    connect(networkGetMap_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyGetMap(QNetworkReply*)));

    connect(networkLegend_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyLegend(QNetworkReply*)));

    connect(networkLogo_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyLogo(QNetworkReply*)));
}

MvQWmsGetClient::~MvQWmsGetClient()
{
    delete getMapRequest_;
    if (networkGetMap_)
        delete networkGetMap_;
    if (networkLegend_)
        delete networkLegend_;
    if (networkLogo_)
        delete networkLogo_;
}

bool MvQWmsGetClient::updateBoundingBox()
{
    //Get current view area in the plot

    MvRequest ctxIn = reqInfo_("_CONTEXT");
    if (!ctxIn || strcmp(ctxIn.getVerb(), "GEOVIEW") != 0)
        return false;

    //ctxIn.print();
    MvQProjInfo projInfo(ctxIn);
    //ctxIn.print();

    QList<float> areaL;

    //Cylindrical
    if (projInfo.get("subpage_map_projection") == "cylindrical") {
        if (projInfo.get("subpage_map_area_definition") == "corners" ||
            projInfo.get("subpage_map_area_definition") == "full") {
            areaL << projInfo.get("subpage_lower_left_latitude").toDouble();
            areaL << projInfo.get("subpage_lower_left_longitude").toDouble();
            areaL << projInfo.get("subpage_upper_right_latitude").toDouble();
            areaL << projInfo.get("subpage_upper_right_longitude").toDouble();
        }
    }


#if 0
	MvRequest ctx;
	MvRequest ctxIn=reqInfo_("_CONTEXT");
	
	ctxIn.print();
	
	char *shareDir=getenv("METVIEW_DIR_SHARE");
	if(shareDir)
	{	
		string path(shareDir);
		path.append("/etc/");

		string defFileName=path+ "GeoViewDef";
		string rulesFileName=path + "GeoViewRules";

		MvLanguage langMetview ( defFileName.c_str(),
				  rulesFileName.c_str(),
				  EXPAND_DEFAULTS);

	        ctx=langMetview.expandOne (ctxIn);
        }
        else
	{
	  	ctx=ctxIn;
	}	

	ctx.print();

	const char* proj= (const char*)ctx("MAP_PROJECTION");
	
	int cnt = ctx.countValues("AREA");
	double dval; 
	QList<float> areaL;
	for(int i=0; i< cnt; i++)
	{
		ctx.getValue(dval,"AREA",i);
	 	areaL << dval;
	}

	//Check if we have the view area definition
	if(!proj || areaL.count() != 4)
	{
		return false;
	}
#endif
    //Max bounding box for the given CRS/SRS
    const char* bbChar = (const char*)reqInfo_("MAX_BOUNDING_BOX");
    QRectF maxBox;
    if (bbChar) {
        QString s(bbChar);
        QStringList lst = s.split("/");
        if (lst.count() == 4) {
            maxBox = QRectF(lst[0].toFloat(), lst[1].toFloat(),
                            lst[2].toFloat() - lst[0].toFloat(),
                            lst[3].toFloat() - lst[1].toFloat());
        }
    }

    if (maxBox.isEmpty()) {
        return false;
    }

    //Current bounding box from the request
    QRectF currentBox;
    QStringList lst = getMapRequest_->item("BBOX").split(",");
    if (lst.count() == 4) {
        currentBox = QRectF(lst[0].toFloat(), lst[1].toFloat(),
                            lst[2].toFloat() - lst[0].toFloat(),
                            lst[3].toFloat() - lst[1].toFloat());
    }

    if (currentBox.isEmpty()) {
        return false;
    }

    //We reached this point only if both view area and
    //bounding box were found!!!!

    if (projInfo.get("subpage_map_projection") == "cylindrical") {
        //areaL: s,w,n,e
        //bbox: mix, miny, max, maxy
        //qDebug() << "area" << areaL;

        QRectF areaBox;

        //For 1.3.0 in epsg:4326 x is lat and y is lon !!!!!
        if (getMapRequest_->request().contains("CRS=", Qt::CaseInsensitive) &&
            getMapRequest_->crs() == "EPSG:4326") {
            areaBox = QRectF(areaL[0], areaL[1], areaL[2] - areaL[0], areaL[3] - areaL[1]);
        }
        else if (getMapRequest_->crs() == "EPSG:4326" || getMapRequest_->crs() == "CRS:84") {
            areaBox = QRectF(areaL[1], areaL[0], areaL[3] - areaL[1], areaL[2] - areaL[0]);
        }

        if (areaBox.isEmpty()) {
            return false;
        }

        if (areaBox.intersects(maxBox)) {
            // maxAreaBox = the intersection of the viewable area
            //and the max bounding box for the srs/c
            QRectF maxAreaBox = areaBox.intersected(maxBox);

            //Find out the relation of the maxAreaBox and the current bounding
            //box in the request
            QRectF resBox;
            if (maxAreaBox != currentBox) {
                resBox = maxAreaBox;
            }

            if (!resBox.isEmpty()) {
                getMapRequest_->setItem("BBOX",
                                        QString::number(resBox.x()) + "," +
                                            QString::number(resBox.y()) + "," +
                                            QString::number(resBox.x() + resBox.width()) + "," +
                                            QString::number(resBox.y() + resBox.height()));

                return true;
            }
        }
    }

    return false;
}

void MvQWmsGetClient::runGetMap()
{
    outFiles_.clear();

    QStringList lst        = getMapRequest_->requestFrame();
    getMapFrameNum_        = lst.count();
    getMapFrameToDownload_ = 0;

    getMapRunStatus_ = false;
    downloadGetMapFrame();
}

void MvQWmsGetClient::downloadGetMapFrame()
{
    //qDebug() << "request" << getMapFrameToDownload_ << getMapRequest_->requestFrame(getMapFrameToDownload_);

    QNetworkRequest netReq(QUrl::fromPercentEncoding(getMapRequest_->requestFrame(getMapFrameToDownload_).toUtf8()));
    //netReq.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());

    getMapReply_ = networkGetMap_->get(netReq);
}

void MvQWmsGetClient::downloadLegend()
{
    if (!legendPath_.isEmpty()) {
        //qDebug() << "legend" << QUrl::fromPercentEncoding(legendPath_.toAscii());

        QNetworkRequest netReq(QUrl::fromPercentEncoding(legendPath_.toUtf8()));
        //netReq.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());
        legendReply_ = networkLegend_->get(netReq);
    }
    else {
        //QApplication::exit();
        downloadLogo();
    }
}

void MvQWmsGetClient::downloadLogo()
{
    if (!logoPath_.isEmpty()) {
        logoReply_ = networkLogo_->get(QNetworkRequest(QUrl::fromPercentEncoding(logoPath_.toUtf8())));
    }
    else {
        QApplication::exit();
    }
}


void MvQWmsGetClient::slotReplyGetMap(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    if (reply->error() != QNetworkReply::NoError) {
        getMapFrameNum_        = 0;
        getMapFrameToDownload_ = -1;

        QString ems = "GetMap request failed!\nError: ";
        ems += reply->errorString();
        marslog(LOG_EROR, "GetMap request failed!\nError: %s ", reply->errorString().toStdString().c_str());
        QApplication::exit();
        return;
    }
    else {
        // temporary file
        QString outFile;
        outFile = marstmp();

        getMapRequest_->setOutFile(getMapFrameToDownload_, outFile);

        QByteArray ba = reply->readAll();

        if (mimeType.isEmpty())
            mimeType = getMimeType(ba);

        //If exception is returned or mime type is
        //different to what was requested
        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml") ||
            !mimeType.contains(getRequestedMimeType(url.toString()))) {
            QString eMsg;
            //readException(ba,eMsg);

            getMapFrameNum_        = 0;
            getMapFrameToDownload_ = -1;

            //marslog(LOG_EROR,"GetMap request failed!\nError: %s ",eMsg.toStdString().c_str());
            marslog(LOG_EROR, "GetMap request failed! ");
            QApplication::exit();
            return;
        }

        QFile out(outFile);
        out.open(QIODevice::WriteOnly);
        out.write(ba);
        out.close();

        getMapFrameToDownload_++;

        if (getMapFrameToDownload_ < getMapFrameNum_) {
            downloadGetMapFrame();
        }
        else {
            getMapFrameNum_        = 0;
            getMapFrameToDownload_ = -1;

            getMapRunStatus_ = true;
            downloadLegend();
            //QApplication::exit();
        }
    }

    reply->deleteLater();
    getMapReply_ = 0;
}

void MvQWmsGetClient::slotReplyLegend(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    if (reply->error() != QNetworkReply::NoError) {
        QString ems = "Legend download failed!\nError: ";
        ems += reply->errorString();
        marslog(LOG_EROR, "Legend download failed!\nError: %s ", reply->errorString().toStdString().c_str());
        //log->error(reply->errorString().toStdString() + "\n");
        downloadLogo();
        //QApplication::exit();
        return;
    }
    else {
        QByteArray ba = reply->readAll();

        //If exception is returned ot mime type is
        //different ot what was requested
        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml") ||
            mimeType.contains("text/plain"))  //||
        //   mimeType != getRequestedMimeType(url.toString()))
        {
            QApplication::exit();
            return;
        }
        else {
            QString outFile = QString::fromStdString(marstmp());

            QFile out(outFile);
            out.open(QIODevice::WriteOnly);
            out.write(ba);
            out.close();

            legendImagePath_ = outFile;

            //QApplication::exit();
            downloadLogo();
        }
    }

    reply->deleteLater();
    legendReply_ = 0;
}


void MvQWmsGetClient::slotReplyLogo(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    if (reply->error() != QNetworkReply::NoError) {
        QString ems = "Logo download failed!\nError: ";
        ems += reply->errorString();
        marslog(LOG_EROR, "Logo download failed!\nError: %s ", reply->errorString().toStdString().c_str());
        //log->error(reply->errorString().toStdString() + "\n");
        QApplication::exit();
        return;
    }
    else {
        QByteArray ba = reply->readAll();

        //If exception is returned ot mime type is
        //different ot what was requested
        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml") ||
            mimeType.contains("text/plain"))  //||
        //   mimeType != getRequestedMimeType(url.toString()))
        {
            QApplication::exit();
            return;
        }
        else {
            QString outFile = QString::fromStdString(marstmp());

            QFile out(outFile);
            out.open(QIODevice::WriteOnly);
            out.write(ba);
            out.close();

            logoImagePath_ = outFile;

            QImage img(outFile);
            if (img.width() > 100) {
                img.scaledToWidth(100, Qt::SmoothTransformation).save(outFile, "png");
            }

            QApplication::exit();
        }
    }

    reply->deleteLater();
    logoReply_ = 0;
}


//=================================
//
// Client for the user interface
//
//=================================

MvQWmsUiClient::MvQWmsUiClient(string& iconFile, MvRequest& req) :
    iconFile_(QString::fromStdString(iconFile)),
    reqInfo_(req)
{
    char* shareDir = getenv("METVIEW_DIR_SHARE");
    if (shareDir) {
        string path(shareDir);
        path.append("/etc/");

        string defFileName   = path + "WmsClientDef";
        string rulesFileName = path + "WmsClientRules";

        MvLanguage langMetview(defFileName.c_str(),
                               rulesFileName.c_str(),
                               EXPAND_DEFAULTS);

        reqInfo_ = langMetview.expandOne(req);
    }


    reqInfo_.print();

    getMapRequest_     = new MvQGetMapRequest;
    lastGetMapRequest_ = new MvQGetMapRequest;

    // Initialize elements from Metview request
    url_     = QString((const char*)reqInfo_("SERVER"));
    version_ = (const char*)reqInfo_("VERSION");

    QStringList timeDimName;

    const char* tdn = (const char*)reqInfo_("TIME_DIMENSIONS");
    if (tdn) {
        QString s(tdn);
        timeDimName = s.split("/");
    }

    getMapRequest_->setRequest(QString((const char*)reqInfo_("REQUEST")), timeDimName);

    clientMode_ = AdvancedMode;
    if ((const char*)reqInfo_("MODE") != 0) {
        QString m(reqInfo_("MODE"));
        if (m == "EXPERT")
            clientMode_ = BasicMode;
        else
            clientMode_ = AdvancedMode;
    }

    if ((const char*)reqInfo_("EXTRA_GETCAP_PAR") != 0) {
        extraGetCapPar_ = QString(reqInfo_("EXTRA_GETCAP_PAR"));
    }

    if ((const char*)reqInfo_("EXTRA_GETMAP_PAR") != 0) {
        extraGetMapPar_ = QString(reqInfo_("EXTRA_GETMAP_PAR"));
    }

    if ((const char*)reqInfo_("HTTP_USER") != 0) {
        httpUser_ = QString(reqInfo_("HTTP_USER"));
    }

    if ((const char*)reqInfo_("HTTP_PASSWORD") != 0) {
        httpPassword_ = QString(reqInfo_("HTTP_PASSWORD"));
    }


    //qDebug() << "Init:" << url_ << version_ << getMapRequest_;

    //Width
    width_      = new MvQOgcIntValue(1024, "WIDTH", "Width:");
    QString val = getMapRequest_->item(width_->requestName());
    if (!val.isEmpty())
        width_->setValue(val.toInt());

    //Height
    height_ = new MvQOgcIntValue(512, "HEIGHT", "Height:");
    val     = getMapRequest_->item(height_->requestName());
    if (!val.isEmpty())
        height_->setValue(val.toInt());

    //Format
    format_ = new MvQOgcList("FORMAT", "Format:");

    //Transparent
    transparent_ = new MvQOgcList("TRANSPARENT", "Transparent:");
    transparent_->setValues(QStringList() << "TRUE"
                                          << "FALSE");
    transparent_->setDisplayValues(QStringList() << "True"
                                                 << "False");
    val = getMapRequest_->item(transparent_->requestName());

    //If it is a new request we set transparency to TRUE by default
    if (val.isEmpty() && getMapRequest_->request().isEmpty()) {
        transparent_->setCurrentValue("TRUE");
    }
    else {
        transparent_->setCurrentValue(val);
    }

    //BgColour
    bgColour_ = new MvQOgcColourValue("#FFFFFF", "BGCOLOUR", "Bg colour:");

    //Layer
    layer_ = new MvQOgcTree("LAYERS", "Layer:");

    //CRS/SRS
    crs_ = new MvQOgcCrsList("CRS", "CRS:");

    //Style
    style_ = new MvQOgcStyleList("STYLES", "Style:");

    //BoundingBox
    requestBbox_    = new MvQOgcBoundingBox("BBOX", "");
    geographicBbox_ = 0;

    //Dimension

    //Network access
    networkGetCap_  = new MvQNetworkAccessManager(this);
    networkPreview_ = new MvQNetworkAccessManager(this);
    networkLegend_  = new MvQNetworkAccessManager(this);
    networkLogo_    = new MvQNetworkAccessManager(this);

    getCapReply_  = 0;
    previewReply_ = 0;
    legendReply_  = 0;
    logoReply_    = 0;

    connect(networkGetCap_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyGetCap(QNetworkReply*)));

    connect(networkPreview_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyPreview(QNetworkReply*)));

    connect(networkLegend_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyLegend(QNetworkReply*)));

    connect(networkLogo_, SIGNAL(replyReadyToProcess(QNetworkReply*)),
            this, SLOT(slotReplyLogo(QNetworkReply*)));

    connect(networkGetCap_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
            this, SLOT(slotAuthentication(QNetworkReply*, QAuthenticator*)));

    connect(networkPreview_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
            this, SLOT(slotAuthentication(QNetworkReply*, QAuthenticator*)));

    connect(networkLegend_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
            this, SLOT(slotAuthentication(QNetworkReply*, QAuthenticator*)));

    connect(networkLogo_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
            this, SLOT(slotAuthentication(QNetworkReply*, QAuthenticator*)));

    previewFile_ = marstmp();
    legendFile_  = marstmp();
    logoFile_    = marstmp();

    //xml namspace
    xlinkNsDeclaration_ = "declare namespace xlink = \"http://www.w3.org/1999/xlink\";";
}

MvQWmsUiClient::~MvQWmsUiClient()
{
    delete width_;
    delete height_;
    delete format_;
    delete transparent_;
    delete bgColour_;
    delete layer_;
    delete crs_;
    delete style_;
    delete requestBbox_;
    delete networkGetCap_;
    delete networkPreview_;
    delete networkLegend_;
    delete networkLogo_;

    clearDimension();
    clearBoundingBox();

    clearPreview();
    clearLegend();
}

void MvQWmsUiClient::reset(QString r)
{
    slotAbortDownloadProcess();

    if (clientMode_ == BasicMode) {
        getMapRequest_->setRequest(r);
    }
    else {
        clearServerDependentData();

        getMapRequest_->setRequest(r);

        QString v = getMapRequest_->item("VERSION");
        if (v.isEmpty()) {
            v = getMapRequest_->item("version");
        }
        url_     = getMapRequest_->guessUrl();
        version_ = v;
    }

    emit clientResetDone();
}


void MvQWmsUiClient::setClientMode(ClientMode mode)
{
    if (clientMode_ == mode)
        return;

    if (mode == AdvancedMode) {
        slotAbortDownloadProcess();

        extraGetMapPar_ = getMapRequest_->item("mv_key_extrapar");

        QString v = getMapRequest_->item("VERSION");
        if (v.isEmpty()) {
            v = getMapRequest_->item("version");
        }

        //qDebug() << "new url:" << getMapRequest_->guessUrl();

        if (url_ != getMapRequest_->guessUrl() ||
            version_ != v) {
            if (v.isEmpty())
                setUrl(getMapRequest_->guessUrl());
            else
                setUrl(getMapRequest_->guessUrl(), v);
        }
    }

    clientMode_ = mode;
}

void MvQWmsUiClient::clearServerDependentData(bool keepRequest)
{
    capability_.clear();
    if (!keepRequest) {
        getMapRequest_->clear();
    }
    format_->clear();
    layer_->clear();
    clearLayerDependentData();
    serviceMeta_.clear();
}

void MvQWmsUiClient::clearLayerDependentData()
{
    crs_->clear();
    style_->clear();
    clearDimension();
    clearBoundingBox();
}

void MvQWmsUiClient::clearDimension()
{
    foreach (MvQOgcDimension* item, dimension_) {
        delete item;
    }
    dimension_.clear();
}

void MvQWmsUiClient::clearBoundingBox()
{
    foreach (MvQOgcBoundingBox* item, bbox_) {
        delete item;
    }
    bbox_.clear();

    if (geographicBbox_) {
        delete geographicBbox_;
        geographicBbox_ = 0;
    }
}

void MvQWmsUiClient::setUrl(const QString& url, const QString version)
{
    if (url_ != url) {
        slotAbortDownloadProcess();
        url_     = url;
        version_ = version;
        clearServerDependentData();
    }
}

void MvQWmsUiClient::setVersion(const QString& version)
{
    if (version_ != version) {
        slotAbortDownloadProcess();
        version_ = version;
        //clearServerDependentData();
    }
}

void MvQWmsUiClient::slotRunGetCapabilities()
{
    lastGetMapRequest_->setRequest(getMapRequest_->request());
    clearServerDependentData(true);  //keeps the original request

    QString r = url_;

    r += "?SERVICE=WMS&";
    if (version_ != "Default") {
        r += "VERSION=" + version_ + "&";
    }
    r += "REQUEST=GetCapabilities";
    if (!extraGetCapPar_.isEmpty()) {
        r += "&" + extraGetCapPar_;
    }

    GuiLog().task() << "Load GetCapabalitites"
                    << " ..in progress";

    StatusMsgHandler::instance()->show("Load GetCapabilitites ...", true);

    QUrl url = QUrl::fromPercentEncoding(r.toUtf8());
    QNetworkRequest nr(url);
    //nr.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());

    getCapReply_ = networkGetCap_->get(QNetworkRequest(nr));
}


void MvQWmsUiClient::downloadPreview(QSize previewSize)
{
    MvQGetMapRequest req;
    req.setRequest(getMapRequest_->requestFrame(0));

    previewSize_ = previewSize;

    QString w = QString::number(previewSize_.width());
    QString h = QString::number(previewSize_.height());

    MvQOgcNode* node = layer_->currentNode();
    if (node) {
        if (!node->attribute("fixedWidth").isEmpty() &&
            node->attribute("fixedWidth").toInt() > 0) {
            w = node->attribute("fixedWidth");
        }
        if (!node->attribute("fixedHeight").isEmpty() &&
            node->attribute("fixedHeight").toInt() > 0) {
            h = node->attribute("fixedHeight");
        }
    }

    req.setItem("WIDTH", w);
    req.setItem("HEIGHT", h);

    GuiLog().task() << "Load preview" << GuiLog().requestKey() << req.request().toStdString();
    //log->setStatus("In progress");
    StatusMsgHandler::instance()->show(tr("Load preview ..."), true);

    QNetworkRequest netReq(QUrl::fromPercentEncoding(req.request().toUtf8()));
    netReq.setOriginatingObject(this);
    //netReq.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());


    previewReply_ = networkPreview_->get(netReq);
}

void MvQWmsUiClient::downloadLegend()
{
    if (!style_->currentLegend().isEmpty()) {
        GuiLog().task() << "Load legend" << GuiLog().requestKey() << style_->currentLegend().toStdString();
        //log->setStatus("In progress");

        StatusMsgHandler::instance()->show(tr("Load legend"), true);

        //Fix for KNMI radar
        QNetworkRequest netReq(QUrl::fromPercentEncoding(style_->currentLegend().toUtf8()));
        netReq.setOriginatingObject(this);
        //netReq.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());
        legendReply_ = networkLegend_->get(netReq);
    }
    else {
        emit legendLoaded(QString());
    }
}

void MvQWmsUiClient::downloadLogo()
{
    MvQOgcNode* node = layer_->currentNode();
    if (node && !node->logo().isEmpty()) {
        GuiLog().task() << "Load logo" << GuiLog().requestKey() << node->logo().toStdString();
        //log->setStatus("In progress");
        StatusMsgHandler::instance()->show(tr("Load logo"), true);

        //Fix for KNMI radar
        QNetworkRequest netReq(QUrl::fromPercentEncoding(node->logo().toUtf8()));
        netReq.setOriginatingObject(this);
        //netReq.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg("egows").arg("egows").toAscii()).toBase64());
        logoReply_ = networkLogo_->get(netReq);
    }
    else {
        emit logoLoaded(QString());
    }
}

void MvQWmsUiClient::setGetMapRequest(QString r)
{
    if (clientMode_ == BasicMode) {
        getMapRequest_->editRequest(r);
        emit getMapRequestChanged(getMapRequest_->request(), getMapRequest_->requestFrame());
    }
}


void MvQWmsUiClient::slotSaveInfo()
{
    // Get info
    MvRequest r("WMSCLIENT");

    r("SERVER")          = url_.toStdString().c_str();
    r("VERSION")         = version_.toStdString().c_str();
    r("REQUEST")         = getMapRequest_->request().toStdString().c_str();
    r("TIME_DIMENSIONS") = timeDimName().join("/").toStdString().c_str();
    //r("NON_TIME_DIMENSIONS") =  nonTimeDimName().join("/").toStdString().c_str();

    //	reqInfo_("SERVICE") = 1;
    if (clientMode_ == BasicMode) {
        r("MODE") = "EXPERT";
    }
    else {
        r("MODE") = "INTERACTIVE";
    }

    r("EXTRA_GETCAP_PAR") = extraGetCapPar_.toStdString().c_str();
    r("EXTRA_GETMAP_PAR") = extraGetMapPar_.toStdString().c_str();

    r("HTTP_USER")     = httpUser_.toStdString().c_str();
    r("HTTP_PASSWORD") = httpPassword_.toStdString().c_str();

    r("LAYER_TITLE")       = layer_->currentDisplayValue().toStdString().c_str();
    r("LAYER_DESCRIPTION") = layer_->currentDescription().toStdString().c_str();
    r("SERVICE_TITLE")     = serviceMeta_["Title"].toStdString().c_str();
    r("LAYER_LEGEND")      = style_->currentLegend().toStdString().c_str();

    MvQOgcNode* node = layer_->currentNode();
    if (node) {
        r("LAYER_LOGO") = node->logo().toStdString().c_str();

        if (!node->attribute("noSubsets").isEmpty()) {
            r("LAYER_NOSUBSETS") = node->attribute("noSubsets").toStdString().c_str();
        }
        if (!node->attribute("fixedWidth").isEmpty()) {
            r("LAYER_FIXEDWITH") = node->attribute("fixedWidth").toStdString().c_str();
        }
        if (!node->attribute("fixedHeight").isEmpty()) {
            r("LAYER_FIXEDHEIGHT") = node->attribute("fixedHeight").toStdString().c_str();
        }
    }

    r("MAX_BOUNDING_BOX") = getMapRequest_->item("BBOX").split(",").join("/").toStdString().c_str();

    //qDebug() << version_;
    //qDebug() << url_;

    MvRequest rout;

    r.print();

    char* shareDir = getenv("METVIEW_DIR_SHARE");
    if (shareDir) {
        string path(shareDir);
        path.append("/etc/");

        string defFileName   = path + "WmsClientDef";
        string rulesFileName = path + "WmsClientRules";

        MvLanguage langMetview(defFileName.c_str(),
                               rulesFileName.c_str(),
                               EXPAND_NO_DEFAULT);

        rout = langMetview.expandOne(r);

        if (!rout)
            rout = r;
    }
    else {
        rout = r;
    }

    rout.print();

    // Save info request
    rout.save(iconFile_.toStdString().c_str());
}


void MvQWmsUiClient::slotAuthentication(QNetworkReply* /*reply*/, QAuthenticator* auth)
{
    auth->setUser("egows");
    auth->setPassword("egows");

    //auth->setUser(httpUser_);
    //auth->setPassword(httpPassword_);
}

void MvQWmsUiClient::slotReplyGetCap(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    GuiLog().task() << "Load GetCapabilities";

    if (reply->error() != QNetworkReply::NoError) {
        GuiLog().error() << reply->errorString().toStdString();
        StatusMsgHandler::instance()->failed();

        emit getCapabilityLoaded();
        //QApplication::exit();
    }
    else {
        QByteArray ba = reply->readAll();

        QString eMsg;
        if (!mimeType.contains("application/vnd.ogc.wms_xml"))  // ||
                                                                //   mimeType.contains("text/xml"))
                                                                //&& mimeType == "application/vnd.ogc.se_xml")
        {
            readException(ba, eMsg);
        }

        if (!eMsg.isEmpty()) {
            capability_.clear();
            GuiLog().error() << eMsg.toStdString();
            emit getCapabilityLoaded();
            StatusMsgHandler::instance()->failed();
        }
        else {
            capability_ = QString(ba);

            //Uncomment these lines to load a getCapabilities file from the disk
            /*QFile file("/var/tmp/dummy-user/PERFORCE/metview_4/src/OgcClient/marc_dla.xml");
    			if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
         			return;

			capability_=QString(file.readAll());*/

            repliedVersion_ = readVersion();
            readService();
            readFormat();
            readLayer();

            updateAfterGetCapLoaded();

            emit getCapabilityLoaded();
            StatusMsgHandler::instance()->done();
        }
    }

    reply->deleteLater();
    getCapReply_ = 0;
}

void MvQWmsUiClient::updateAfterGetCapLoaded()
{
    QString val;

    if (lastGetMapRequest_->request().isEmpty()) {
        return;
    }

    val = lastGetMapRequest_->item(width_->requestName());
    width_->setValue(val.toInt());

    val = lastGetMapRequest_->item(height_->requestName());
    height_->setValue(val.toInt());

    val = lastGetMapRequest_->item(transparent_->requestName());
    transparent_->setCurrentValue(val);

    val = lastGetMapRequest_->item(format_->requestName());
    format_->setCurrentValue(val);

    val = lastGetMapRequest_->item(layer_->requestName());
    layer_->setCurrentValue(val);

    updateAfterLayerLoaded();
}

void MvQWmsUiClient::updateAfterLayerLoaded()
{
    //lastGetMapRequest_->setRequest(getMapRequest_->request());

    QString val;

    MvQOgcNode* node = layer_->currentNode();
    if (node) {
        if (!node->attribute("fixedWidth").isEmpty()) {
            val = node->attribute("fixedWidth");
            if (val.toInt() > 0)
                width_->setValue(val.toInt());
        }
        if (!node->attribute("fixedHeight").isEmpty()) {
            val = node->attribute("fixedHeight");
            if (val.toInt() > 0)
                height_->setValue(val.toInt());
        }
    }

    //readLayerAbstract();
    readStyle();
    readBoundingBox();  //bounding box should be called before crs!!!!!
    readCrs();
    readGeographicBoundingBox();
    readDimension();
    readAttribution();

    val = lastGetMapRequest_->item(style_->requestName());
    style_->setCurrentValue(val);

    val = lastGetMapRequest_->item(crs_->requestName());
    crs_->setCurrentValue(val);

    updatRequestBoundingBox();

    foreach (MvQOgcDimension* dim, dimension_) {
        val = lastGetMapRequest_->item(dim->requestName());
        dim->setCurrentValues(val);
    }

    buildGetMapRequest();

    //qDebug() << lastGetMapRequest_->request() << "\n" << getMapRequest_->request();
}

void MvQWmsUiClient::slotReplyPreview(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    GuiLog().task() << "Load preview";

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    if (reply->error() != QNetworkReply::NoError) {
        GuiLog().error() << reply->errorString().toStdString();
        emit previewLoaded(QString());
        StatusMsgHandler::instance()->failed();
    }
    else {
        QString outFile = previewFile_;
        QByteArray ba   = reply->readAll();

        if (mimeType.isEmpty())
            mimeType = getMimeType(ba);

        //qDebug() << "preview mimeType" << mimeType;

        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml") ||
            !mimeType.contains(getRequestedMimeType(url.toString()))) {
            QString eMsg;
            readException(ba, eMsg);

            GuiLog().error() << eMsg.toStdString();
            emit previewLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else if (mimeType.contains("text/plain")) {
            QString eMsg(ba);

            GuiLog().error() << eMsg.toStdString();
            emit previewLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else {
            QImage img = QImage::fromData(ba);
            if (!img.isNull()) {
                img = img.scaledToWidth(previewSize_.width(), Qt::SmoothTransformation);
                img.save(outFile, "png");
            }
            else {
                QFile out(outFile);
                out.open(QIODevice::WriteOnly);
                out.write(ba);
                out.close();
            }

            emit previewLoaded(outFile);
            StatusMsgHandler::instance()->done();
        }
    }

    reply->deleteLater();
    previewReply_ = 0;
}

void MvQWmsUiClient::slotReplyLegend(QNetworkReply* reply)
{
    //Here, reply is not necessary the legendReply_ because the
    //request might have been redirected!!
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    GuiLog().task() << "Load legend";

    if (reply->error() != QNetworkReply::NoError) {
        GuiLog().error() << reply->errorString().toStdString();
        emit legendLoaded(QString());
        StatusMsgHandler::instance()->failed();
    }
    else {
        QString outFile = legendFile_;
        QByteArray ba   = reply->readAll();

        if (mimeType.isEmpty())
            mimeType = getMimeType(ba);

        //qDebug() << "mime" << mimeType << getRequestedMimeType(url.toString());

        //If exception is returned or mime type is
        //different to what was requested
        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml"))
        //    || mimeType != getRequestedMimeType(url.toString()))
        {
            QString eMsg;
            readException(ba, eMsg);

            GuiLog().error() << eMsg.toStdString();
            emit legendLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else if (mimeType.contains("text/plain")) {
            QString eMsg(ba);

            GuiLog().error() << eMsg.toStdString();
            emit legendLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else {
            //qDebug() << outFile;

            QFile out(outFile);
            out.open(QIODevice::WriteOnly);
            out.write(ba);
            out.close();

            emit legendLoaded(outFile);
            StatusMsgHandler::instance()->done();
        }
    }

    reply->deleteLater();
    legendReply_ = 0;
}

void MvQWmsUiClient::slotReplyLogo(QNetworkReply* reply)
{
    QNetworkRequest r = reply->request();
    QUrl url          = r.url();

    //qDebug() << url.toString();

    QString mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();

    GuiLog().task() << "Load logo";

    if (reply->error() != QNetworkReply::NoError) {
        GuiLog().error() << reply->errorString().toStdString();
        emit logoLoaded(QString());
        StatusMsgHandler::instance()->failed();
    }
    else {
        QString outFile = logoFile_;
        QByteArray ba   = reply->readAll();

        if (mimeType.isEmpty())
            mimeType = getMimeType(ba);

        //qDebug() << "mime" << mimeType << getRequestedMimeType(url.toString());

        //If exception is returned or mime type is
        //different to what was requested
        if (mimeType.contains("application/vnd.ogc.se_xml") ||
            mimeType.contains("text/xml"))
        //    || mimeType != getRequestedMimeType(url.toString()))
        {
            QString eMsg;
            readException(ba, eMsg);

            GuiLog().error() << eMsg.toStdString();
            emit logoLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else if (mimeType.contains("text/plain")) {
            QString eMsg(ba);

            GuiLog().error() << eMsg.toStdString();
            emit logoLoaded(QString());
            StatusMsgHandler::instance()->failed();
        }
        else {
            //qDebug() << outFile;

            QFile out(outFile);
            out.open(QIODevice::WriteOnly);
            out.write(ba);
            out.close();

            QImage img(outFile);
            if (img.width() > 100) {
                img.scaledToWidth(100, Qt::SmoothTransformation).save(outFile, "png");
            }

            emit logoLoaded(outFile);
            StatusMsgHandler::instance()->done();
        }
    }

    reply->deleteLater();
    logoReply_ = 0;
}


bool MvQWmsUiClient::previewDownloadActive()
{
    return previewReply_ && previewReply_->isRunning();
}

bool MvQWmsUiClient::legendDownloadActive()
{
    return legendReply_ && legendReply_->isRunning();
}

void MvQWmsUiClient::slotAbortDownloadProcess()
{
    if (getCapReply_ && getCapReply_->isRunning()) {
        GuiLog().task() << "Load GetCapabalitites";
        GuiLog().error() << "Interrupted";
        StatusMsgHandler::instance()->failed();

        getCapReply_->deleteLater();
        getCapReply_ = 0;
        emit getCapabilityLoaded();
    }
    else if (previewReply_ && previewReply_->isRunning()) {
        GuiLog().task() << "Load preview";
        GuiLog().error() << "Interrupted";
        StatusMsgHandler::instance()->failed();

        previewReply_->deleteLater();
        previewReply_ = 0;
        clearPreview();
        emit previewLoaded(previewFile_);
    }
    else if (legendReply_ && legendReply_->isRunning()) {
        GuiLog().task() << "Load legend";
        GuiLog().error() << "Interrupted";
        StatusMsgHandler::instance()->failed();

        legendReply_->deleteLater();
        legendReply_ = 0;
        clearLegend();
        emit legendLoaded(legendFile_);
    }
    else if (logoReply_ && logoReply_->isRunning()) {
        GuiLog().task() << "Load logo";
        GuiLog().error() << "Interrupted";
        StatusMsgHandler::instance()->failed();

        logoReply_->deleteLater();
        logoReply_ = 0;
        clearLogo();
        emit logoLoaded(logoFile_);
    }
}

QString MvQWmsUiClient::readVersion()
{
    QString result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    defaultNsDeclaration_ = "declare default element namespace \"http://www.opengis.net/wms\";";

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//WMS_Capabilities/data(@version)");
    query.evaluateTo(&result);

    if (result.simplified().isEmpty()) {
        query.setQuery("doc($myDoc)//WMT_MS_Capabilities/data(@version)");
        query.evaluateTo(&result);
        defaultNsDeclaration_.clear();
    }

    buffer.close();

    //Remove linebreak!!

    return result.simplified();
}

void MvQWmsUiClient::readService()
{
    serviceMeta_.clear();

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    //query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Service/data(Title)");
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Service");
    query.evaluateTo(&result);

    //serviceTitle_=result.simplified();

    QXmlItem item(result.next());
    while (!item.isNull()) {
        if (item.isNode()) {
            query.setFocus(item);

            QString str;

            query.setQuery(defaultNsDeclaration_ + "./data(Title)");
            query.evaluateTo(&str);
            serviceMeta_["Title"] = str.simplified();

            query.setQuery(defaultNsDeclaration_ + "./data(Abstract)");
            query.evaluateTo(&str);
            serviceMeta_["Abstract"] = str.simplified();

            QStringList tags;
            tags << "ContactPerson"
                 << "ContactOrganization"
                 << "ContactPosition"
                 << "AddressType"
                 << "Address"
                 << "City"
                 << "StateOrProvince"
                 << "PostCode"
                 << "Country"
                 << "ContactVoiceTelephone"
                 << "ContactFacsimileTelephone"
                 << "ContactElectronicMailAddress";

            foreach (QString t, tags) {
                str.clear();
                QString q = defaultNsDeclaration_ + ".//data(" + t + ")";
                query.setQuery(q);
                query.evaluateTo(&str);
                serviceMeta_[t] = str.simplified();
            }

            break;
        }
        item = result.next();
    }

    buffer.close();

    //Remove linebreak!!
}


void MvQWmsUiClient::readFormat()
{
    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);

    if (repliedVersion_ > "1.0") {
        query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Capability/Request/GetMap/data(Format)");
    }
    else {
        query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Capability/Request/Map/data(Format)");
    }

    query.evaluateTo(&result);

    QStringList lst;
    query.getAtomicValues(result, lst);
    lst.sort();
    format_->setValues(lst);
    format_->setDisplayValues(lst);

    buffer.close();
}

void MvQWmsUiClient::readLayer()
{
    //Dom
    QDomDocument doc("mydocument");

    if (!doc.setContent(capability_, true)) {
        return;
    }

    QDomElement docElem = doc.documentElement();
    readLayer(docElem, layer_->root());
}

void MvQWmsUiClient::readLayer(QDomElement& docElem, MvQOgcNode* parent)
{
    QDomNode dNode = docElem.firstChild();
    while (!dNode.isNull()) {
        QDomElement dElem = dNode.toElement();
        if (!dElem.isNull()) {
            if (dElem.tagName() == "Layer") {
                MvQOgcNode* layer = new MvQOgcNode;
                parent->addChild(layer);

                QDomNode title = dNode.namedItem("Title");
                if (!title.isNull()) {
                    //qDebug() << title.toElement().text().simplified();
                    layer->setDisplayValue(title.toElement().text().simplified());
                }

                QDomNode name = dNode.namedItem("Name");
                if (!name.isNull()) {
                    layer->setValue(name.toElement().text().simplified());
                }

                QDomNode desc = dNode.namedItem("Abstract");
                if (!desc.isNull()) {
                    layer->setDescription(desc.toElement().text().simplified());
                }
                else if (layer->parent()) {
                    layer->setDescription(layer->parent()->description());
                }

                QDomNamedNodeMap att = dNode.attributes();
                for (int i = 0; i < att.size(); i++) {
                    QDomAttr da = att.item(i).toAttr();
                    if (!da.isNull()) {
                        layer->addAttribute(da.name(), da.value());
                    }
                }

                readLayer(dElem, layer);
            }
            else {
                readLayer(dElem, parent);
            }
        }

        dNode = dNode.nextSibling();
    }
}


void MvQWmsUiClient::readStyle()
{
    if (layer_->currentValue().isEmpty())
        return;

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/Style");
    query.evaluateTo(&result);

    QXmlItem item(result.next());
    QStringList nameLst, titleLst, abstractLst, legendLst;
    while (!item.isNull()) {
        if (item.isNode()) {
            QString name, title, abstract, legend;

            //QXmlQuery query;
            query.setFocus(item);

            //Name
            query.setQuery(defaultNsDeclaration_ + "./data(Name)");
            query.evaluateTo(&name);
            nameLst << name.simplified();

            //Title
            query.setQuery(defaultNsDeclaration_ + "./data(Title)");
            query.evaluateTo(&title);
            titleLst << title.simplified();

            //Abstract
            query.setQuery(defaultNsDeclaration_ + "./data(Abstract)");
            query.evaluateTo(&abstract);
            abstractLst << abstract.simplified();

            //Legend url
            query.setQuery(defaultNsDeclaration_ + xlinkNsDeclaration_ + "string(./LegendURL/OnlineResource/@xlink:href)");
            query.evaluateTo(&legend);
            legendLst << legend.simplified();

            style_->setValues(nameLst);
            style_->setDisplayValues(titleLst);
            style_->setDescriptions(abstractLst);
            style_->setLegends(legendLst);
        }
        item = result.next();
    }

    buffer.close();
}

void MvQWmsUiClient::readCrs()
{
    if (layer_->currentValue().isEmpty())
        return;

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));
    //query.bindVariable("myCrsName", QVariant(crsRequestName()));
    if (crsRequestName() == "SRS") {
        query.setQuery("doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/data(SRS)");
    }
    else {
        query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/data(CRS)");
    }

    query.evaluateTo(&result);

    QStringList lst;
    query.getAtomicValues(result, lst);

    if (repliedVersion_ <= "1.1.0") {
        QStringList lstOri = lst;
        lst.clear();
        foreach (QString s, lstOri) {
            lst << s.split(" ");
        }
    }

    if (repliedVersion_ >= "1.3.0") {
        QStringList lstOri = lst;
        lst.clear();
        foreach (QString s, lstOri) {
            if (s == "EPSG:4326" || s == "CRS:84") {
                lst << s;
            }
            else {
                foreach (MvQOgcBoundingBox* bb, bbox_) {
                    if (s == bb->crs()) {
                        lst << s;
                        break;
                    }
                }
            }
        }
    }

    lst.removeDuplicates();
    lst.sort();

    crs_->setValues(lst);
    crs_->setRequestName(crsRequestName());
    crs_->setDisplayName(crsDisplayName());

    buffer.close();
}

void MvQWmsUiClient::readBoundingBox()
{
    if (layer_->currentValue().isEmpty())
        return;

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/BoundingBox");
    query.evaluateTo(&result);

    QXmlItem item(result.next());
    while (!item.isNull()) {
        if (item.isNode()) {
            QMap<QString, QString> att;
            query.getAttributes(item, att);

            MvQOgcBoundingBox* bb = new MvQOgcBoundingBox(att);

            //Remove all previously defined (in the ancestors) bboxes
            foreach (MvQOgcBoundingBox* bitem, bbox_) {
                if (bitem->crs() == bb->crs()) {
                    bbox_.removeOne(bitem);
                    delete bitem;
                    break;
                }
            }

            bbox_.push_back(bb);

            //qDebug() << "bb" <<  bb->crs() << bb->minX() << bb->maxX();
        }
        item = result.next();
    }

    buffer.close();
}


void MvQWmsUiClient::readGeographicBoundingBox()
{
    if (layer_->currentValue().isEmpty())
        return;

    QStringList str;
    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));

    if (repliedVersion_ >= "1.3.0") {
        query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/EX_GeographicBoundingBox");
        query.evaluateTo(&result);

        QMap<QString, QString> att;

        QXmlItem item(result.next());
        while (!item.isNull()) {
            if (item.isNode()) {
                QString val;

                //QXmlQuery query;
                query.setFocus(item);

                query.setQuery(defaultNsDeclaration_ + "./data(westBoundLongitude)");
                query.evaluateTo(&val);
                att["westBoundLongitude"] = val.simplified();

                query.setQuery(defaultNsDeclaration_ + "./data(eastBoundLongitude)");
                query.evaluateTo(&val);
                att["eastBoundLongitude"] = val.simplified();

                query.setQuery(defaultNsDeclaration_ + "./data(southBoundLatitude)");
                query.evaluateTo(&val);
                att["southBoundLatitude"] = val.simplified();

                query.setQuery(defaultNsDeclaration_ + "./data(northBoundLatitude)");
                query.evaluateTo(&val);
                att["northBoundLatitude"] = val.simplified();

                if (geographicBbox_) {
                    delete geographicBbox_;
                }
                geographicBbox_ = new MvQOgcGeoBoundingBox(att);  //new MvQXmlElementNode(query,item);
                break;
            }

            item = result.next();
        }
    }
    else {
        query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/LatLonBoundingBox");

        query.evaluateTo(&result);

        QXmlItem item(result.next());
        while (!item.isNull()) {
            if (item.isNode()) {
                QMap<QString, QString> att;
                query.getAttributes(item, att);
                if (geographicBbox_) {
                    delete geographicBbox_;
                }
                geographicBbox_ = new MvQOgcGeoBoundingBox(att);  //new MvQXmlElementNode(query,item);
                break;
            }
            item = result.next();
        }
    }
}

void MvQWmsUiClient::readDimension()
{
    if (layer_->currentValue().isEmpty())
        return;

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/Dimension");
    query.evaluateTo(&result);

    QXmlItem item(result.next());
    while (!item.isNull()) {
        if (item.isNode()) {
            QMap<QString, QString> att;
            QString value;

            query.getAttributes(item, att);
            query.getAtomicValue(item, value);

            MvQOgcDimension* dim = new MvQOgcDimension(att, value);

            for (int i = 0; i < dimension_.count(); i++) {
                if (dim->name().compare(dimension_[i]->name(), Qt::CaseInsensitive) == 0) {
                    MvQOgcDimension* item = dimension_[i];
                    dimension_.removeAt(i);
                    delete item;
                    break;
                }
            }

            if (dim->name().compare("time", Qt::CaseInsensitive) == 0) {
                dim->setRequestName("TIME");
                dim->setDisplayName("Time:");
            }
            else if (dim->name().compare("elevation", Qt::CaseInsensitive) == 0) {
                dim->setRequestName("ELEVATION");
                dim->setDisplayName("Elevation:");
            }
            else {
                QString dname = dim->name();
                dname         = dname.toUpper();
                dname         = "DIM_" + dname;
                dim->setRequestName(dname);
                dname += " :";
                dim->setDisplayName(dname);
            }

            dimension_.push_back(dim);
        }
        item = result.next();
    }

    if (repliedVersion_ >= "1.3.0")
        return;

    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/Extent");
    query.evaluateTo(&result);

    item = result.next();
    while (!item.isNull()) {
        if (item.isNode()) {
            QMap<QString, QString> att;
            QString value;

            query.getAttributes(item, att);
            query.getAtomicValue(item, value);

            //MvQXmlElementNode *elem=new MvQXmlElementNode(query,item);
            foreach (MvQOgcDimension* dim, dimension_) {
                if (dim->name() == att["name"]) {
                    dim->setAttributes(att);
                    dim->setValues(value);
                    break;
                }
            }
        }
        item = result.next();
    }
}

void MvQWmsUiClient::readAttribution()
{
    if (layer_->currentValue().isEmpty())
        return;

    MvQOgcNode* layerNode = layer_->currentNode();
    if (!layerNode)
        return;

    QXmlResultItems result;

    QByteArray ba = capability_.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    MvQXmlQuery query;
    query.bindVariable("myDoc", &buffer);
    query.bindVariable("myLayer", QVariant(layer_->currentValue()));
    query.setQuery(defaultNsDeclaration_ + "doc($myDoc)//Layer[normalize-space(Name) = $myLayer]/ancestor-or-self::*/Attribution");
    query.evaluateTo(&result);

    QXmlItem item(result.next());
    while (!item.isNull()) {
        if (item.isNode()) {
            QString logo;

            //QXmlQuery query;
            query.setFocus(item);

            //Logo url
            query.setQuery(defaultNsDeclaration_ + xlinkNsDeclaration_ + "string(./LogoURL/OnlineResource/@xlink:href)");
            query.evaluateTo(&logo);
            layerNode->setLogo(logo.simplified());
        }
        item = result.next();
    }

    buffer.close();
}

void MvQWmsUiClient::readException(QByteArray ba, QString& msg)
{
    //if(xmlMsg.isEmpty())
    //	return;

    QXmlResultItems result;

    //QByteArray ba=xmlMsg.toUtf8();
    QBuffer buffer(&ba);  // This is a QIODevice.
    buffer.open(QIODevice::ReadOnly);

    QString ns;
    if (repliedVersion_ >= "1.3.0")
        ns = "declare default element namespace \"http://www.opengis.net/ogc\";";

    MvQXmlQuery query;
    query.setMessageHandler(queryMsgHandler_);
    query.bindVariable("myDoc", &buffer);
    query.setQuery(ns + "doc($myDoc)//ServiceExceptionReport/ServiceException");
    query.evaluateTo(&result);

    QXmlItem item(result.next());
    if (item.isNull()) {
        query.setQuery("doc($myDoc)//ServiceExceptionReport/ServiceException");
        query.evaluateTo(&result);
        item = result.next();
    }

    while (!item.isNull()) {
        if (item.isNode()) {
            msg += "Exception: ";

            QMap<QString, QString> att;
            QString value;

            query.getAttributes(item, att);
            query.getAtomicValue(item, value);
            msg += att["code"].simplified() + "\n";

            if (!value.isEmpty()) {
                msg += value;
                msg += '\n';
            }
        }
        item = result.next();
    }

    //If XML parsing failed
    if (queryMsgHandler_->fatalFound()) {
        msg += "Exception: parsing of exception document failed!!\n";
        foreach (QString s, queryMsgHandler_->fatalMessages()) {
            msg += s + '\n';
        }
    }

    queryMsgHandler_->clear();
    buffer.close();
}

void MvQWmsUiClient::buildGetMapRequest()
{
    if (layer_->currentValue().isEmpty())
        return;

    getMapRequest_->clear();

    QString s;
    QString str = url_;
    str += "?SERVICE=WMS";

    //Version
    /*if(version_ != "Default")
	{
		str+="&VERSION=";
		str+=version_;
	}*/

    str += "&VERSION=";
    str += repliedVersion_;

    //Request
    str += "&REQUEST=GetMap";

    //Layers
    str += "&" + layer_->requestName() + "=" + layer_->currentValue();

    //Style
    str += "&" + style_->requestName() + "=" + style_->currentValue();

    //srs or crs
    str += "&" + crs_->requestName() + "=" + crs_->currentValue();

    //bbox
    str += "&BBOX=" +
           requestBbox_->minX() + "," +
           requestBbox_->minY() + "," +
           requestBbox_->maxX() + "," +
           requestBbox_->maxY();

    //width
    str += "&WIDTH=" + QString::number(width_->value());
    str += "&HEIGHT=" + QString::number(height_->value());

    //Format
    str += "&" + format_->requestName() + "=" + format_->currentValue();

    //Transparent
    str += "&" + transparent_->requestName() + "=" + transparent_->currentValue();

    //Dimensions
    foreach (MvQOgcDimension* dim, dimension_) {
        str += "&";
        str += dim->requestName();
        str += "=";
        str += dim->currentValues();
    }

    if (!extraGetMapPar_.isEmpty()) {
        str += "&" + extraGetMapPar_;
    }

    getMapRequest_->setRequest(str, timeDimName());

    currentGetMapRequest_ = getMapRequest_;

    //qDebug() << getMapRequest_->requestFrame();

    //str+="&stream=false";

    //getMapRequest_=str;

    //saveGetMapRequest(currentGetMapRequest_);

    emit getMapRequestChanged(getMapRequest_->request(), getMapRequest_->requestFrame());
}


//===========================================
//
// Get/Set methods
//
//===========================================

//Format
QStringList MvQWmsUiClient::formatDisplayValues() const
{
    return format_->displayValues();
}

QString MvQWmsUiClient::formatCurrentDisplayValue() const
{
    return format_->currentDisplayValue();
}

void MvQWmsUiClient::slotSetFormatFromDpy(QString value)
{
    if (format_->currentDisplayValue() != value) {
        format_->setCurrentDisplayValue(value);
        buildGetMapRequest();
    }
}

//Transparent
QStringList MvQWmsUiClient::transparentDisplayValues() const
{
    return transparent_->displayValues();
}

QString MvQWmsUiClient::transparentCurrentDisplayValue() const
{
    return transparent_->currentDisplayValue();
}

void MvQWmsUiClient::setTransparentCurrentDisplayValue(QString value)
{
    if (transparent_->currentDisplayValue() != value) {
        transparent_->setCurrentDisplayValue(value);
        buildGetMapRequest();
    }
}

//Width
QString MvQWmsUiClient::width() const
{
    return QString::number(width_->value());
}

void MvQWmsUiClient::setWidth(QString value)
{
    if (width_->value() != value.toInt()) {
        width_->setValue(value.toInt());
        buildGetMapRequest();
    }
}

//Height
QString MvQWmsUiClient::height() const
{
    return QString::number(height_->value());
}

void MvQWmsUiClient::setHeight(QString value)
{
    if (height_->value() != value.toInt()) {
        height_->setValue(value.toInt());
        buildGetMapRequest();
    }
}

//Extra par
void MvQWmsUiClient::setExtraGetCapPar(QString value)
{
    if (extraGetCapPar_ != value) {
        extraGetCapPar_ = value;
    }
}

void MvQWmsUiClient::setExtraGetMapPar(QString value)
{
    if (extraGetMapPar_ != value) {
        extraGetMapPar_ = value;
        buildGetMapRequest();
    }
}

//Style
QStringList MvQWmsUiClient::styleDisplayValues() const
{
    return style_->displayValues();
}

QStringList MvQWmsUiClient::styleDescriptions() const
{
    return style_->descriptions();
}

int MvQWmsUiClient::styleCurrentIndex() const
{
    return style_->currentIndex();
}

void MvQWmsUiClient::setStyleCurrentIndex(int index)
{
    if (style_->currentIndex() != index) {
        style_->setCurrentIndex(index);
        buildGetMapRequest();
    }
}


//CRS
QStringList MvQWmsUiClient::crsDisplayValues() const
{
    return crs_->displayValues();
}

QString MvQWmsUiClient::crsCurrentDisplayValue() const
{
    return crs_->currentDisplayValue();
}

void MvQWmsUiClient::setCrsCurrentDisplayValue(QString value)
{
    if (crs_->currentDisplayValue() != value) {
        slotAbortDownloadProcess();
        crs_->setCurrentDisplayValue(value);
        updatRequestBoundingBox();
        buildGetMapRequest();
    }
}

//Layer
int MvQWmsUiClient::layerCurrentIndex()
{
    return 0;
    //return layer_->values().indexOf(layer_->currentValue());
}

QStringList MvQWmsUiClient::layerDisplayValues() const
{
    return QStringList();
    //return layer_->displayValues();
}

QStringList MvQWmsUiClient::layerDescriptions() const
{
    return QStringList();
    //qDebug() << layer_->descriptions();
    //return layer_->descriptions();
}

void MvQWmsUiClient::setLayerFromDpy(MvQOgcNode* node)
{
    slotAbortDownloadProcess();

    clearLayerDependentData();

    layer_->setCurrentNode(node);

    lastGetMapRequest_->setRequest(getMapRequest_->request());

    updateAfterLayerLoaded();
}


//BBOX
void MvQWmsUiClient::setBoundingBoxFromDpy(QString minX, QString maxX, QString minY, QString maxY)
{
    slotAbortDownloadProcess();
    requestBbox_->setArea(minX, maxX, minY, maxY);
    buildGetMapRequest();
}

MvQOgcBoundingBox MvQWmsUiClient::lastBoundingBox() const
{
    QString lastValue = lastGetMapRequest_->item("BBOX");
    QStringList lst   = lastValue.split(",");
    MvQOgcBoundingBox bb;
    if (lst.count() == 4) {
        bb.setArea(lst[0], lst[2], lst[1], lst[3]);
    }
    return bb;
}

MvQOgcBoundingBox* MvQWmsUiClient::currentBoundingBox() const
{
    for (int i = bbox_.count() - 1; i >= 0; i--) {
        if (bbox_[i]->crs() == crs_->currentValue()) {
            return bbox_[i];
        }
    }

    return 0;
}

//Dimensions
QStringList MvQWmsUiClient::dimensionNameToDpy() const
{
    QStringList lst;
    /*foreach(MvQOgcDimensionList *dim,dimension_)
	{
	    lst << dim->displayName();
	}*/

    return lst;
}

QStringList MvQWmsUiClient::dimensionToDpy(QString /*dimDpyName*/) const
{
    /*foreach(MvQOgcDimensionList *dim,dimension_)
	{
	    if(dim->displayName() == dimDpyName)
	    {
		return dim->displayValues();
	    }
	}*/

    return QStringList();
}

void MvQWmsUiClient::setDimensionFromDpy(QString dimDpyName, QString val)
{
    slotAbortDownloadProcess();

    foreach (MvQOgcDimension* dim, dimension_) {
        if (dim->displayName() == dimDpyName) {
            //dim->setCurrentDisplayValue(val);
            dim->setCurrentValues(val);
            buildGetMapRequest();
            return;
        }
    }
}

void MvQWmsUiClient::setDimensionFromDpy(QString /*dimDpyName*/, QStringList /*val*/)
{
    /*foreach(MvQOgcDimensionList *dim,dimension_)
	{
	    if(dim->displayName() == dimDpyName)
	    {
		//dim->setCurrentDisplayValues(val);
		setCurrentValues(val);
		buildGetMapRequest();
		return;
	    }
	}*/
}

QString MvQWmsUiClient::crsQueryName()
{
    if (repliedVersion_ < QString("1.3.0")) {
        return QString("SRS");
    }
    else {
        return QString("CRS");
    }
}

QString MvQWmsUiClient::crsRequestName()
{
    if (repliedVersion_ < QString("1.3.0")) {
        return QString("SRS");
    }
    else {
        return QString("CRS");
    }
}

QString MvQWmsUiClient::crsDisplayName()
{
    if (repliedVersion_ < QString("1.3.0")) {
        return QString("SRS:");
    }
    else {
        return QString("CRS:");
    }
}

QStringList MvQWmsUiClient::timeDimName()
{
    QStringList timeDimName;

    foreach (MvQOgcDimension* dim, dimension_) {
        if (dim->isTime()) {
            timeDimName << dim->requestName();
        }
    }
    return timeDimName;
}

void MvQWmsUiClient::clearPreview()
{
    //if(previewFile_ != emptyFileNameString_)
    //{
    QFile f(previewFile_);

    if (!f.remove()) {
        //qDebug() << "MvQZoomStackLevel::clearPreview() ---> Preview file" << imgFileName_ << "could not be deleted!";
    }
    //previewFile_ = emptyFileNameString_;
    //}
}

void MvQWmsUiClient::clearLegend()
{
    //if(previewFile_ != emptyFileNameString_)
    //{
    QFile f(legendFile_);

    if (!f.remove()) {
        //qDebug() << "MvQZoomStackLevel::clearPreview() ---> Preview file" << imgFileName_ << "could not be deleted!";
    }
    //previewFile_ = emptyFileNameString_;
    //}
}

void MvQWmsUiClient::clearLogo()
{
    QFile f(logoFile_);

    if (!f.remove()) {
    }
}


void MvQWmsUiClient::updatRequestBoundingBox()
{
    requestBbox_->clear();
    bool foundBb = false;

    //Check if bbox is available for the current crs.
    //It is mandatory from 1.3.0 !!!
    foreach (MvQOgcBoundingBox* bb, bbox_) {
        if (bb->crs() == crs_->currentValue()) {
            foundBb = true;
            requestBbox_->setArea(bb->minX(), bb->maxX(), bb->minY(), bb->maxY());
            break;
        }
    }

    if (!foundBb && geographicBbox_ != 0) {
        //For 1.3.0 epsg:4326 lat is x and lon is y!!!!!
        if (repliedVersion_ >= "1.3.0") {
            if (crs_->currentValue() == "EPSG:4326") {
                requestBbox_->setArea(geographicBbox_->minY(),
                                      geographicBbox_->maxY(),
                                      geographicBbox_->minX(),
                                      geographicBbox_->maxX());

                foundBb = true;
            }
            else if (crs_->currentValue() == "CRS:84") {
                requestBbox_->setArea(geographicBbox_->minX(),
                                      geographicBbox_->maxX(),
                                      geographicBbox_->minY(),
                                      geographicBbox_->maxY());

                foundBb = true;
            }
        }
        else {
            //Else for older versions lat-lon we try to use the geographic bounding box
            requestBbox_->setArea(geographicBbox_->minX(),
                                  geographicBbox_->maxX(),
                                  geographicBbox_->minY(),
                                  geographicBbox_->maxY());

            foundBb = true;
        }
    }

    //For special non-geographical projections where no crs is defined (e.g. cross-section)
    if (!foundBb && crs_->currentValue().isEmpty() && geographicBbox_ != 0) {
        requestBbox_->setArea(geographicBbox_->minX(),
                              geographicBbox_->maxX(),
                              geographicBbox_->minY(),
                              geographicBbox_->maxY());
    }
}
