/***************************** 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 *************************************/

#ifndef MvQWmsClient_H
#define MvQWmsClient_H

#include <QAbstractMessageHandler>
#include <QFile>
#include <QMap>
#include <QObject>
#include <QStringList>

#include "MvRequest.h"

#include "MvQOgcParam.h"


class QAuthenticator;
class QDomElement;
class QNetworkReply;

class MvQNetworkAccessManager;
class MvQGetMapRequest;

class MvQProjInfo : public QMap<QString,QString>
{
public:
	MvQProjInfo(const MvRequest &);	
	QString get(QString);
		
protected:	
	void parseProj4String(const char*);
	void parseRequest(const MvRequest &);
};


class MvQWmsMessageHandler : public  QAbstractMessageHandler
{
public:
    MvQWmsMessageHandler(QObject *parent=0) : QAbstractMessageHandler(parent) {};
    void clear() {fatalMsg_.clear();}
    bool fatalFound() {return fatalMsg_.count() > 0;}
    QStringList fatalMessages() {return fatalMsg_;}
    
protected:   
    void handleMessage(QtMsgType,const QString &,const QUrl &,const QSourceLocation &);
    
    QStringList fatalMsg_;
  
};  

class MvQWmsClientBase : public QObject
{
public:
	virtual ~MvQWmsClientBase();
	QStringList supportedMimeType() {return supportedMimeType_;}
	QStringList supportedCrs() {return supportedCrs_;}

protected:
	MvQWmsClientBase();

	QStringList supportedMimeType_;
	QStringList supportedCrs_;

	QString getMimeType(QByteArray);
	QString getRequestedMimeType(QString);
	
	MvQWmsMessageHandler *queryMsgHandler_;
};


class MvQWmsGetClient : public MvQWmsClientBase
{
	Q_OBJECT

public:
	MvQWmsGetClient(MvRequest&);
	~MvQWmsGetClient();

	MvQGetMapRequest* getMapRequest() {return getMapRequest_;}
	void setGetMapRequest(QString);

	QStringList outFiles() {return outFiles_;}
	
	void runGetMap();
	bool getMapRunStatus() {return getMapRunStatus_;}
	QString legendImagePath() {return legendImagePath_;}
	QString logoImagePath() {return logoImagePath_;}
	bool requestChanged() {return requestChanged_;}
	
	
public slots:	
	void slotReplyGetMap(QNetworkReply*);
	void slotReplyLegend(QNetworkReply*);
	void slotReplyLogo(QNetworkReply*);

protected:	
	bool updateBoundingBox();
	void downloadGetMapFrame();
	void downloadLegend();
	void downloadLogo();
		
	MvQGetMapRequest* getMapRequest_;
				
	MvQNetworkAccessManager *networkGetMap_;
	MvQNetworkAccessManager *networkLegend_;
	MvQNetworkAccessManager *networkLogo_;

	QNetworkReply *getMapReply_;
	QNetworkReply *legendReply_;
	QNetworkReply *logoReply_;

	int getMapFrameNum_;
	int getMapFrameToDownload_;

	MvRequest      reqInfo_;
	QString        iconFile_;
	QStringList    outFiles_;
	bool 	       getMapRunStatus_;
	QString        legendPath_;
	QString 	legendImagePath_;
	QString        logoPath_;
	QString 	logoImagePath_;
	bool          requestChanged_;

}; 



class MvQWmsUiClient : public MvQWmsClientBase
{
	Q_OBJECT

public:
	MvQWmsUiClient(string&,MvRequest&);
	~MvQWmsUiClient();

	enum ClientMode {BasicMode,AdvancedMode};

	QString url() {return url_;}
	void setUrl(const QString&,const QString version="Default");
	QString version() {return version_;}
	void setVersion(const QString&);
	MvQGetMapRequest* getMapRequest() {return getMapRequest_;}
	void setGetMapRequest(QString);

	QString getCapabilityDoc() {return capability_;}

	QStringList outFiles() {return outFiles_;}

	ClientMode clientMode() {return clientMode_;}
	void setClientMode(ClientMode);

	QStringList formatDisplayValues() const;
	QString formatCurrentDisplayValue() const;

	QStringList transparentDisplayValues() const;
	QString transparentCurrentDisplayValue() const;
	void setTransparentCurrentDisplayValue(QString);
	
	void setWidth(QString);
	QString width() const;
	void setHeight(QString);
	QString height() const;

	QStringList crsDisplayValues() const;
	QString crsCurrentDisplayValue() const;
	void setCrsCurrentDisplayValue(QString);
	QString crsDisplayName();

	QStringList styleDisplayValues() const;
	QStringList styleDescriptions() const;
	int styleCurrentIndex() const;
	void setStyleCurrentIndex(int);

	void setLayerFromDpy(MvQOgcNode*);
	QStringList layerDisplayValues() const;
	QStringList layerDescriptions() const;
	const QList<MvQOgcDimension*>& dimension() {return dimension_;}
	QStringList dimensionNameToDpy() const;
	QStringList dimensionToDpy(QString) const;
	void setDimensionFromDpy(QString,QString);
	void setDimensionFromDpy(QString,QStringList);
	void setBoundingBoxFromDpy(QString,QString,QString, QString);
	const MvQOgcBoundingBox *boundingBox() {return requestBbox_;}
	MvQOgcBoundingBox lastBoundingBox() const;
	MvQOgcBoundingBox* currentBoundingBox() const;

	QString   extraGetCapPar() {return extraGetCapPar_;}
	QString   extraGetMapPar() {return extraGetMapPar_;}
	void 	  setExtraGetCapPar(QString);
	void 	  setExtraGetMapPar(QString);

	MvQOgcTree* layer() {return layer_;}
	int layerCurrentIndex();
	QString layerName() {return layer_->currentValue();}
	QString layerTitle() {return layer_->currentDisplayValue();}
	QString layerAbstract() {return layer_->currentDescription();}

	QString iconFile() {return iconFile_;}
	void setFileNameInfo(string& name) {iconFile_ = QString::fromStdString(name);}
	void setRequestInfo(MvRequest& req) {reqInfo_ = req;}

	void downloadPreview(QSize s=QSize(512,256));
	void downloadLegend();
	void downloadLogo();

	void reset(QString);

	QMap<QString,QString>  serviceMetaData() {return serviceMeta_;}

	bool previewDownloadActive();
	bool legendDownloadActive();

	
public slots:
	void slotReplyGetCap(QNetworkReply*);
	void slotReplyPreview(QNetworkReply*);
	void slotReplyLegend(QNetworkReply*);
	void slotReplyLogo(QNetworkReply*);
	void slotRunGetCapabilities();
	void slotAbortDownloadProcess();
	void slotSaveInfo();

	void slotAuthentication(QNetworkReply *,QAuthenticator *);

	void slotSetFormatFromDpy(QString);

signals:
	void getCapabilityLoaded();
	void getMapRequestChanged(QString,QStringList); 
	void previewLoaded(QString);
	void legendLoaded(QString);
	void logoLoaded(QString);	
	void clientResetDone();

protected:
	void clearServerDependentData(bool keepRequest=false);
	void clearLayerDependentData();
	void clearDimension();
	void clearBoundingBox();
	void runGetCapabilities();
	void buildGetMapRequest();
	void saveGetMapRequest(QMap<QString,QString> &);
	void downloadGetMap();

	QString readVersion();
	void readService();
	void readFormat();
	void readLayer();
	void readLayer(QDomElement &,MvQOgcNode *);
	//void readLayerAbstract();
	void readStyle();
	void readBoundingBox();
	void readCrs();
	void readDimension();
	void readGeographicBoundingBox();
	void readAttribution();
	void readException(QByteArray,QString&);
	void updatRequestBoundingBox();
	QString crsQueryName();
	QString crsRequestName();

	QStringList timeDimName();

	void clearPreview();
	void clearLegend();
	void clearLogo();

	void updateAfterGetCapLoaded();
	void updateAfterLayerLoaded();

	QString    url_;
	QString    version_;
	QString    repliedVersion_;
	QString    capability_;
	MvQGetMapRequest* getMapRequest_;
	MvQGetMapRequest* currentGetMapRequest_;
	MvQGetMapRequest* lastGetMapRequest_;
	
	//Global
	MvQOgcList*  format_;
	MvQOgcList*  transparent_;
	MvQOgcIntValue*  width_;
	MvQOgcIntValue*  height_;
	MvQOgcColourValue* bgColour_;

	//Layer
	MvQOgcTree*	   layer_;
	QString 	   layerAbstract_;
	MvQOgcCrsList*	   crs_;
	MvQOgcStyleList*   style_;

	MvQOgcBoundingBox* requestBbox_;
	MvQOgcGeoBoundingBox* geographicBbox_;
	QList<MvQOgcBoundingBox*>  bbox_;
	QList<MvQOgcDimension*>   dimension_;	

	MvQNetworkAccessManager *networkGetCap_;
	MvQNetworkAccessManager *networkPreview_;
	MvQNetworkAccessManager *networkLegend_;
	MvQNetworkAccessManager *networkLogo_;

	QNetworkReply *getCapReply_;
	QNetworkReply *previewReply_;
	QNetworkReply *legendReply_;
	QNetworkReply *logoReply_;

	QString        iconFile_;
	MvRequest      reqInfo_;
	QStringList    outFiles_;
	
	QSize 		previewSize_;
		
	ClientMode     clientMode_;
	QString defaultNsDeclaration_;
	QString xlinkNsDeclaration_;
	QString previewFile_;
	QString legendFile_;
	QString logoFile_;
	QMap<QString,QString> serviceMeta_;

	QString   extraGetCapPar_;
	QString   extraGetMapPar_;

	QString httpUser_;
	QString httpPassword_;   
}; 

#endif
