///////
   //    MySQL Database class for ht://Check
   //
   //    Copyright (c) 1999-2004 Comune di Prato - Prato - Italy
   //    Some Portions Copyright (c) 1995-2000 The ht://Dig Group <www.htdig.org>
   //    Some Portions Copyright (c) 2008 Devise.IT srl <http://www.devise.it/>
   //    Author: Gabriele Bartolini - Prato - Italy <angusgb@users.sourceforge.net>
   //
   //    For copyright details, see the file COPYING in your distribution
   //    or the GNU General Public License version 2 or later 
   //    <http://www.gnu.org/copyleft/gpl.html>
   //
   //    $Id: HtmysqlDB.h,v 1.30 2009/08/26 12:25:58 angusgb Exp $
   //
   //    Started: 28.06.1999
///////

#ifndef _HTMYSQLDB_H
#define _HTMYSQLDB_H

#ifdef HAVE_STD
#include <iostream>
#include <string>
#include <set>
#ifdef HAVE_NAMESPACES
using namespace std;
#endif
#else
#include <iostream.h>
#include <string.h>
#include <set.h>
#endif /* HAVE_STD */

#include "Htmysql.h"
#include "_Server.h"
#include "_Url.h"
#include "HtCookie.h"
#include "SchedulerEntry.h"
#include "HtmlStatement.h"
#include "HtmlAttribute.h"
#include "Link.h"
#include "RunInfo.h"
#include "Dictionary.h"
#include "AccessibilityCheck.h"
   
class HtmysqlDB : public Htmysql
{

///////
   //    Public Interface
///////

   public:

//      HtmysqlDB(const std::string &host, const std::string &db,
//         const std::string &user, const std::string &passwd);

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

      HtmysqlDB(const std::string &db,
#ifdef HAVE_LOAD_DEFAULTS
	const std::string &File,
#endif
	const std::string& Group,
	const std::string &_ClientCharset, const std::string& _DBCharset,
	int *argc, char ***argv);

      virtual ~HtmysqlDB();


///////
   //    Set methods for protected attributes
///////
      
      // Set the length for the Index regarding
      // the Url field in the Schedule and Url tables
      // This method is publicly accessible
      void SetURL_Index_Length(const int &i) { URL_Index_Length = i; }

///////
   //    Access methods to protected attributes
///////
      
      const std::string &GetDB() {return MySQLDB;}
#ifdef HAVE_LOAD_DEFAULTS
      const std::string &GetHost() {return MySQLHost;}
      const std::string &GetUser() {return MySQLUser;}
#endif
      const std::string &GetDBSignature() {return DBSignature;}
      const int GetURL_Index_Length() {return URL_Index_Length;}


///////
   //    Connection to the MySQL database server
///////
      
      virtual int Connect(); // Let's connect with it
      
///////
   //    ht://Check Database creation -- with a MySQL query script
///////
      
      virtual int CreateDatabase();


///////
   //    ht://Check Database drop -- with a MySQL query script
///////
      
      virtual int DropDatabase();
      virtual int DropTables(); // Keep the database, but recreate ht://Check tables only


///////
   //    Function to insert an object of various type
///////

      int Insert (SchedulerEntry&);    // Insert a scheduler entry
                                        // into Schedule table and
                                        // updates its ID
                                       
      int Insert (const _Server&);          // Insert a record into Server table       
      int Insert (const _Url&);             // Insert a record into Url table       
      int Insert (const HtmlStatement&);    // Insert a record into
                                       // HtmlStatement table       
      int Insert (const HtmlAttribute&);    // Insert a record into
                                       // HtmlAttribute table       
      int Insert (const Link&);             // Insert a record into Link table       
      int Insert (const RunInfo&);          // Insert general info into the db
      int Insert (const HtCookie&);   // Insert a record into Cookie table       
      int Insert (const AccessibilityCheck&);    // Insert a record into
                                       // AccessibilityCheck table       
      
      // Insert a link description into the HtmlStatement
      int InsertHtmlStatementLinkDescription(const unsigned int IDUrl,
		          const unsigned int TagPosition, const std::string& LinkDescription);

///////
   //    Search functions, given a filter and a HtmysqlQueryResult
///////

      // Look for a scheduler entry
      int Search (SchedulerEntry &filter, HtmysqlQueryResult &result);
//      int Search (_Server &filter, HtmysqlQueryResult &result);


///////
   //    Query execution and storing method
   //    If an error occurs, -1 is returned
   //    If result is specified, we store the result of the query and
   //    the function returns the number of rows found, else 0.
///////

      int Query(const std::string &SQLStatement, HtmysqlQueryResult *result = 0,
         Query_Type qt = Htmysql_Stored);


///////
   //    Create a SQL string for a filter (Where clause)
///////

      void CreateFilter(std::ostringstream &SQLStatement, SchedulerEntry &filter);
//      void CreateFilter(std::string &SQLStatement, _Server &filter);
      

///////
   //    Get next element from a result of a query, given a HtmysqlQueryResult
   //    and a storing object (for example, a SchedulerEntry, a _Url, ...)
   //    Returns 0 if the end of the query has been reached.
///////

      int GetNextElement (SchedulerEntry &dest, HtmysqlQueryResult &result);
//      int GetNextElement (_Server &dest, HtmysqlQueryResult &result);


///////
   //    Manage the table with anchors and the link table
///////

   int AnchorsTable(ostream& output = std::cout);
   int AnchorsNotFound(ostream& output = std::cout);
   int CreateAnchorsTable();
   int SetAnchorsResults(Link &LinkTmp);
   

///////
   //    Create the indexes for the link table only at the end
   //    because they are not useful before. This can save a lot
   //    of time due to continous updates of indexes when a new
   //    entry for the link table is added.
///////

   int CreateLinkTableIndexes();



 ///////
    //    Set the Link results (at the end of the crawl)
    //    Look for all the links that have 'NotChecked' flag in the LinkResult
    //    field. For each of them, it checks all of the links, and see if
    //    they are eithrt found or not retrieved or broken or redirected.
    //    Then it updates the Link table with the right flag.
    //    Now the BadEncoded case is treated as well.
 ///////

   int SetLinkResults(ostream& output = std::cout);


 ///////
    //    Show the broken links
 ///////

   int ShowBrokenLinks(ostream& output = std::cout);


///////
   //    Show the status codes retrieved
///////

   int ShowStatusCode(ostream &output = std::cout);


///////
   //    Show the content types per server
///////

   int ShowContentTypesPerServer(ostream &output = std::cout);

///////
   //    Calculate the size to be added to URLs (links of the 'Direct' type)
   //    After executing a query, it updates SizeAdd field of the URL table
   //	 A value of bytes to be added to a URL (an HTML document for now)
   //	 depends on the attributes used to link to another URL. For example:
   //    images are called usually with <IMG src="URL A">. This is considered
   //    as a direct link and the size of URL A is being added to the SizeAdd
   //    field of the URL calling it. But this is added only once, even if
   //    inside the document it's called twice, 3 times, a hundred times.
   //    Indeed we suppose the user has a cache system on his computer.
   //    By adding a URL size with the SizeAdd field, we obtain an approximate
   //    URL weight.
///////

   int CalculateUrlSizeAdd(ostream &output = std::cout);


///////
   // Updates a scheduler entry's status
///////
   int UpdateStatus(const SchedulerEntry& entry);


///////
   //    Set the SQL BIG TABLES option
   //    Return 0 if fails
///////

      virtual int SetSQLBigTableOption();

///////
   //    Optimizie the database
///////

      virtual int Optimize();

///////      
   //    Set the list of available charsets
///////      
      void LoadAvailableCharsets(const std::string& c);

///////
   //    Public Attributes
///////
   
   protected:
   
      std::string   MySQLDB;       // Database to be connected with

#ifdef HAVE_LOAD_DEFAULTS
      std::string   MySQLHost;     // Host running a MySQL daemon
      std::string   MySQLUser;     // Authentication information - User
      std::string   MySQLPasswd;   // and password
      int      MySQLPort;     // Port number
      std::string   MySQLSocket;   // Socket name
#endif

      // This variable holds the length of the URL Index
      // in the URL and Schedule tables   
      int      URL_Index_Length;

      std::string   DBSignature;   // Signature of the DB (db@host);
      std::string   ClientCharset;     // Database client charset (default none);
      std::string   DBCharset;     // Database charset (default none);

      typedef std::set<std::string> CharsetsMap;
      CharsetsMap AvailableCharsets;  // list of available charsets
      
#ifdef HAVE_LOAD_DEFAULTS
      void LoadDefaults(const std::string &File,
         MYSQL_LOAD_DEFAULTS_ARGTWO Group, int *argc, char ***argv);
#endif

      //void AppendSQLTextField(std::string &Dest, const char *source);
      void AppendSQLTextField(std::string &Dest, const char* source);
      void AppendSQLTextField(std::string &Dest, const std::string source);
      void AppendSQLTextField(std::ostringstream &Dest, const std::string source);
      void AppendSQLTextField(std::ostringstream &Dest, const char* source);
};

#endif
