
///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//           Application Programming Interface           //
//                                                       //
//                  Library: SAGA_API                    //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//                      metadata.h                       //
//                                                       //
//          Copyright (C) 2009 by Olaf Conrad            //
//                                                       //
//-------------------------------------------------------//
//                                                       //
// This file is part of 'SAGA - System for Automated     //
// Geoscientific Analyses'.                              //
//                                                       //
// This library is free software; you can redistribute   //
// it and/or modify it under the terms of the GNU Lesser //
// General Public License as published by the Free       //
// Software Foundation, either version 2.1 of the        //
// License, or (at your option) any later version.       //
//                                                       //
// This library is distributed in the hope that it will  //
// be useful, but WITHOUT ANY WARRANTY; without even the //
// implied warranty of MERCHANTABILITY or FITNESS FOR A  //
// PARTICULAR PURPOSE. See the GNU Lesser General Public //
// License for more details.                             //
//                                                       //
// You should have received a copy of the GNU Lesser     //
// General Public License along with this program; if    //
// not, see <http://www.gnu.org/licenses/>.              //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//    contact:    Olaf Conrad                            //
//                Institute of Geography                 //
//                University of Hamburg                  //
//                Germany                                //
//                                                       //
//    e-mail:     oconrad@saga-gis.org                   //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
#ifndef HEADER_INCLUDED__SAGA_API__metadata_H
#define HEADER_INCLUDED__SAGA_API__metadata_H


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
/** \file metadata.h
* A flexible class for the storage and management of meta data.
* Standard storage format is the extended markup language (XML).
* @see CSG_MetaData
* @see CSG_HTTP
*/


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
#include "api_core.h"


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
class SAGA_API_DLL_EXPORT CSG_MetaData
{
	friend class CSG_HTTP;

public:
								CSG_MetaData		(void);
	bool						Create				(void);

								CSG_MetaData		(const CSG_MetaData &MetaData);
	bool						Create				(const CSG_MetaData &MetaData);

								CSG_MetaData		(const CSG_String &File, const SG_Char *Extension = NULL);
	bool						Create				(const CSG_String &File, const SG_Char *Extension = NULL);

								CSG_MetaData		(CSG_File &File);
	bool						Create				(CSG_File &File);

	virtual						~CSG_MetaData		(void);
	void						Destroy				(void);

	bool						Load				(const CSG_String &File, const SG_Char *Extension = NULL);
	bool						Save				(const CSG_String &File, const SG_Char *Extension = NULL) const;

	bool						Load				(CSG_File &Stream);
	bool						Save				(CSG_File &Stream)       const;

	bool						Load_HTTP			(const CSG_String &Server, const CSG_String &Path, const SG_Char *Username = NULL, const SG_Char *Password = NULL);

	bool						from_XML			(const char       *XML, size_t Length, const char *Encoding = "UTF-8");
	bool						from_XML			(const CSG_String &XML);
	bool						to_XML				(      CSG_String &XML)  const;

	bool						Load_JSON			(const CSG_String &File);
	bool						Save_JSON			(const CSG_String &File) const;

	bool						from_JSON			(const CSG_String &JSON);
	bool						to_JSON				(      CSG_String &JSON) const;

	bool						Assign				(const CSG_MetaData &MetaData, bool bAddChildren = true);

	CSG_MetaData &				operator  =			(const CSG_MetaData &MetaData) { Assign   (MetaData, true);	return( *this ); }
	CSG_MetaData &				operator +=			(const CSG_MetaData &MetaData) { Add_Child(MetaData, true);	return( *this ); }

	void						Set_Name			(const CSG_String &Name) { m_Name = Name; }
	bool						Cmp_Name			(const CSG_String &String, bool bNoCase =  true) const;
	const CSG_String &			Get_Name			(void)                   const { return( m_Name ); }
	const CSG_String &			Get_Content			(void)                   const { return( m_Content );	}
	const SG_Char *				Get_Content			(int Index)              const { return( Get_Child(Index) ? Get_Child(Index)->Get_Content().c_str() : NULL );	}
	const SG_Char *				Get_Content			(const CSG_String &Name) const;
	bool						Get_Content			(const CSG_String &Name, CSG_String &Value)	const;
	bool						Get_Content			(const CSG_String &Name, double     &Value)	const;
	bool						Get_Content			(const CSG_String &Name, int        &Value)	const;
	bool						Get_Content			(const CSG_String &Name, sLong      &Value)	const;
	void						Set_Content			(const CSG_String &Content)        { m_Content = Content; }
	void						Fmt_Content			(const char    *Format, ...);
	void						Fmt_Content			(const wchar_t *Format, ...);
	bool						Cmp_Content			(const CSG_String &String, bool bNoCase = false) const;

	CSG_MetaData *				Get_Parent			(void) const	{	return( m_pParent );	}

	int							Get_Count			(void) const                    { return( (int)m_Children.Get_Size() ); }
	int							Get_Children_Count	(void) const                    { return( (int)m_Children.Get_Size() ); }
	CSG_MetaData *				Get_Child			(int Index)              const	{ return( Index >= 0 && Index < (int)m_Children.Get_Size() ? *((CSG_MetaData **)m_Children.Get_Entry((size_t)Index)) : NULL ); }
	CSG_MetaData *				Get_Child			(const CSG_String &Name) const;
	CSG_MetaData *				Add_Child			(void);
	CSG_MetaData *				Add_Child			(const CSG_String &Name);
	CSG_MetaData *				Add_Child			(const CSG_String &Name, const CSG_String &Content);
	CSG_MetaData *				Add_Child			(const CSG_String &Name, double            Content);
	CSG_MetaData *				Add_Child			(const CSG_String &Name, int               Content);
	CSG_MetaData *				Add_Child			(const CSG_String &Name, sLong             Content);
	CSG_MetaData *				Add_Child			(const CSG_MetaData &MetaData, bool bAddChildren = true);
	CSG_MetaData *				Ins_Child			(                                                   int Position);
	CSG_MetaData *				Ins_Child			(const CSG_String &Name                           , int Position);
	CSG_MetaData *				Ins_Child			(const CSG_String &Name, const CSG_String &Content, int Position);
	CSG_MetaData *				Ins_Child			(const CSG_String &Name, double            Content, int Position);
	CSG_MetaData *				Ins_Child			(const CSG_String &Name, int               Content, int Position);
	CSG_MetaData *				Ins_Child			(const CSG_String &Name, sLong             Content, int Position);
	CSG_MetaData *				Ins_Child			(const CSG_MetaData &MetaData                     , int Position, bool bAddChildren = true);
	bool						Mov_Child			(int from_Index, int to_Index);
	bool						Del_Child			(int Index);
	bool						Del_Child			(const CSG_String &Name);

	bool						Add_Children		(const CSG_MetaData &MetaData);
	bool						Del_Children		(int Depth = 0, const SG_Char *Name = NULL);

	CSG_MetaData *				operator ()			(int Index             ) const { return(  Get_Child(Index) ); }
	CSG_MetaData *				operator ()			(const CSG_String &Name) const { return(  Get_Child(Name ) ); }
	CSG_MetaData &				operator []			(int Index             )       { return( *Get_Child(Index) ); }
	CSG_MetaData &				operator []			(const CSG_String &Name)       { return( *Get_Child(Name ) ); }
	const CSG_MetaData &		operator []			(int Index             ) const { return( *Get_Child(Index) ); }
	const CSG_MetaData &		operator []			(const CSG_String &Name) const { return( *Get_Child(Name ) ); }

	int							Get_Property_Count	(void)                   const { return( m_Prop_Names.Get_Count() ); }
	const CSG_String &			Get_Property_Name	(int Index)              const { return( m_Prop_Names[Index] ); }
	const SG_Char *				Get_Property		(int Index)              const { return( Index >= 0 && Index < m_Prop_Values.Get_Count() ? m_Prop_Values[Index].c_str() : NULL ); }
	const SG_Char *				Get_Property		(const CSG_String &Name) const { return( Get_Property(_Get_Property(Name)) ); }
	bool						Get_Property		(const CSG_String &Name, CSG_String &Value) const;
	bool						Get_Property		(const CSG_String &Name, double     &Value) const;
	bool						Get_Property		(const CSG_String &Name, int        &Value) const;
	bool						Get_Property		(const CSG_String &Name, sLong      &Value) const;
	bool						Add_Property		(const CSG_String &Name, const CSG_String &Value);
	bool						Add_Property		(const CSG_String &Name, double            Value);
	bool						Add_Property		(const CSG_String &Name, int               Value);
	bool						Add_Property		(const CSG_String &Name, sLong             Value);
	bool						Set_Property		(const CSG_String &Name, const CSG_String &Value, bool bAddIfNotExists = true);
	bool						Set_Property		(const CSG_String &Name, double            Value, bool bAddIfNotExists = true);
	bool						Set_Property		(const CSG_String &Name, int               Value, bool bAddIfNotExists = true);
	bool						Set_Property		(const CSG_String &Name, sLong             Value, bool bAddIfNotExists = true);
	bool						Cmp_Property		(const CSG_String &Name, const CSG_String &String, bool bNoCase = false) const;
	bool						Del_Property		(const CSG_String &Name);
	bool						Del_Property		(int i);

	CSG_String					asText				(int Flags = 0) const;
	class CSG_Table				Get_Table			(int Flags = 0) const;


private:

	CSG_MetaData(CSG_MetaData *pParent);


	CSG_Array					m_Children;

	CSG_MetaData				*m_pParent, *m_pDummy;

	CSG_String					m_Name, m_Content;

	CSG_Strings					m_Prop_Names, m_Prop_Values;


	void						_On_Construction	(void);

	int							_Get_Child			(const CSG_String &Name) const;
	int							_Get_Property		(const CSG_String &Name) const;

	void						_Load				(class wxXmlNode *pNode);
	void						_Save				(class wxXmlNode *pNode) const;


	//-----------------------------------------------------
	friend class CSG_WebRequestSync;
};


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
class SAGA_API_DLL_EXPORT CSG_HTTP
{
public:
	CSG_HTTP									(void);
	bool						Create			(void);

	CSG_HTTP									(const CSG_String &Server, const CSG_String &User = "", const CSG_String &Password = "");
	bool						Create			(const CSG_String &Server, const CSG_String &User = "", const CSG_String &Password = "");

	virtual						~CSG_HTTP		(void);
	bool						Destroy			(void);

	bool						is_Connected	(void) const { return( m_pHTTP != NULL ); }

	bool						Request			(const CSG_String &Request, CSG_Bytes    &Answer);
	bool						Request			(const CSG_String &Request, CSG_MetaData &Answer);
	bool						Request			(const CSG_String &Request, CSG_String   &Answer);
	bool						Request			(const CSG_String &Request, const SG_Char *File);


private:

	class wxHTTP				*m_pHTTP = NULL;


	class wxInputStream *		_Request		(const CSG_String &Request);

};

//---------------------------------------------------------
SAGA_API_DLL_EXPORT bool		SG_FTP_Download	(const CSG_String &Target_Directory, const CSG_String &Source, const CSG_String &User = "", const CSG_String &Password = "", unsigned short Port = 21, bool bBinary = true, bool bVerbose = false);


///////////////////////////////////////////////////////////
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
class SAGA_API_DLL_EXPORT CSG_WebRequestSync
{
public:
	CSG_WebRequestSync							(void);
	bool						Create			(void);

	CSG_WebRequestSync							(const CSG_String &Server, const CSG_String &User = "", const CSG_String &Password = "");
	bool						Create			(const CSG_String &Server, const CSG_String &User = "", const CSG_String &Password = "");

	bool						Destroy			(void);

	bool						Request			(const CSG_String &Request, CSG_Bytes     &Bytes );
	bool						Request			(const CSG_String &Request, CSG_MetaData  &XML   );
	bool						Request			(const CSG_String &Request, CSG_String    &String);
	bool						Request			(const CSG_String &Request, const SG_Char *File  );

	static bool					Request			(const CSG_String &Server, const CSG_String &Request, CSG_Bytes     &Bytes );
	static bool					Request			(const CSG_String &Server, const CSG_String &Request, CSG_MetaData  &XML   );
	static bool					Request			(const CSG_String &Server, const CSG_String &Request, CSG_String    &String);
	static bool					Request			(const CSG_String &Server, const CSG_String &Request, const SG_Char *File  );


private:

	CSG_String					m_Server, m_User, m_Password;

};


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
#endif // #ifndef HEADER_INCLUDED__SAGA_API__metadata_H
