/************************* * * * * * * * * * * * * ***************************
    Copyright (c) 1999-2005 Ryan Bobko
                       ryan@ostrich-emulators.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     
************************** * * * * * * * * * * * * **************************/

#ifndef PLUGINS_H
#define PLUGINS_H

#include "qhaccconstants.h"

#include <qstring.h>

#include <vector>
#include <memory>
using namespace std;

class QHacc;
class TableCol;
class TableRow;
class TableGet;
class PluginInfo;
class TableSelect;
class TableUpdate;
class QHaccResultSet;
class QHaccTable;

class QDate;
class QRect;
class QPoint;
class QPainter;

enum AtomicOp { BEGIN, COMMIT, ROLLBACK };

class PluginInfo;

class QHaccPlugin {
 public:
	/** 
	 * Provide information on the capacilities of this plugin
	 */
	virtual const PluginInfo& info() const =0;
};

// we'll use these typedefs when calling the libraries
typedef QHaccPlugin * (* Creator)();
typedef void (* Destroyer)( QHaccPlugin * ) ;


/****************************************************************/
/**                                                            **/
/** QHACCIOPLUGIN                                              **/
/**   A class with some amount of I/O capability. This is a    **/
/**   baseclass for importers, exporters, and also QHACC_HOME  **/
/**   readers.                                                 **/
/**                                                            **/
/**   An importer should at least implement load() and exprt() **/
/**   An exporter should at least implement imprt() and save() **/
/**                                                            **/
/****************************************************************/

class QHaccIOPlugin : public QHaccPlugin {
 public:

	/**
	 * Connect to the given QHACC_HOME, but don't load any data. This gives the
	 * plugins a chance to verify connection to an external database, or perform
	 * a sanity-check on the given QHACC_HOME. In-depth checking is not really
	 * needed until load() is called, usually immediately afterward.
	 * @param eng The QHacc engine, should it be needed
	 * @param home The location of the datafile(s) we will connect to in load()
	 * @param error Any error that is raised by the connection
	 * @return True, if the load worked
	 */
	virtual bool connect( QHacc * eng, const QString& home, QString& error ) =0;

	/**
	 * Load data from the home (from connect() ) into the plugin's datastore.
	 * Importers must overload this function meaningfully, because they will
	 * read foreign QHACC_HOMEs and then exprt() the data to QHacc.
	 * @param error Any error that is raised by the load
	 * @return True, if the load worked
	 **/
	virtual bool load( QString& error ) =0;

	/**
	 * Furnish the internal data to other objects. Importers need this function,
	 * because they must export whatever they have in their internal structures
	 * to the QHacc engine. The resulting data must be referentially valid
	 * @param rs A set of six datasets correlating to the LocalFiles' structure
	 * @return True, in all cases
	 */
	virtual bool exprt( QHaccResultSet * rs ) =0;
	
	/**
	 * Load the data furnished by some other exprt() function. Exporters need
	 * to reimplement this function meaningfully to be able to read current data
	 * from the engine. Note that the data in @p rs is not necessarily in 
	 * order to satisfy referential integrity. This must be ensured in the plugin
	 * @param rs The data to load
	 * @return True, in all cases
	 **/
	virtual bool imprt( QHaccResultSet * rs ) =0;

	/**
	 * Save data. Exporters need this function to save what they're exporting.
	 * @param error Any error that is raised by the save
	 * @return True, if the save works
	 **/
	virtual bool save( QString& error ) =0;
};

/****************************************************************/
/** QHACCDBPLUGIN                                              **/
/**   Finally, a class that can load and save, and also        **/
/**   interact with a database!                                **/
/**                                                            **/
/****************************************************************/
class QHaccDBPlugin : public QHaccIOPlugin {
 public:
	virtual bool load( QString& error ) =0;
	virtual bool load( Table, const QHaccResultSet * ) =0;

	/**
	 * Create a creation script for the given QHACC_HOME
	 * @param home The QHACC_HOME to be created
	 * @return The creation script
	 */
	virtual QString create( const QString& home ) const =0;

	/**
	 * @return the error code from QHaccResultSet, or QHaccResultSet::VALID
	 */
	virtual int add( Table, const TableRow& ) =0;

	virtual void updateWhere( Table, const TableSelect&, const TableUpdate& ) =0;
	virtual void updateWhere( Table, const TableSelect&, const TableRow& ) =0;

	virtual auto_ptr<QHaccResultSet> getWhere( Table, vector<TableSelect>,
																						 uint& retrows ) =0;
	virtual auto_ptr<QHaccResultSet> getWhere( Table, const TableGet&,
																						 vector<TableSelect>,
																						 uint& retrows ) =0;
	virtual auto_ptr<QHaccResultSet> getWhere( Table, const TableSelect&, 
																						 uint& retrows ) =0;
	
	virtual void deleteWhere( Table, const TableSelect& ) =0;

	virtual TableCol max( Table, int col ) =0;
	virtual TableCol min( Table, int col ) =0;

	/**
	 * How many rows are in the given table?
	 * @param t The table in question
	 * @returns The number of rows in the given table
	 */
	virtual uint cnt( Table t ) =0;  // rows in the given table

	/**
	 * @returns True, if the datastore needs saving
	 */
	virtual bool dirty() const =0; // data needs to be saved?

	/**
	 * Prepare the database for a large data load
	 * @param t The table that will be loaded
	 * @param num The number of rows that will be added
	 */
	virtual void startLoad( Table t, uint num =0 ) =0;

	/**
	 * Bring the given table out of loading setup
	 * @param t The table
	 */
	virtual void stopLoad( Table t ) =0;

	/**
	 * Create or commit an atomic transaction (subject to db availability)
	 * @param name The name of the transaction. This is mostly unused.
	 * @param op What to do with the transacton
	 */
	virtual void setAtom( AtomicOp op, QString name ="dbatom" ) =0;
};

/****************************************************************/
/**                                                            **/
/** QHACCREPORTPLUGIN                                          **/
/**   A class to provide reporting functionality.              **/
/**                                                            **/
/****************************************************************/

class QHaccReportPlugin : public QHaccPlugin {
 public:
	/**
	 * Initialize the plugin. Call this function before using the plugin
	 */
	virtual void setup( QHacc * eng ) =0;

	/**
	 * Create a table with the rows of the report in it (in order
	 * of output). 
	 * @param home A QHACC_HOME string passed from the command line
	 * @param title The title of the report
	 * @param err Any error message the was generated from parsing @p home
	 * @param bool True, if @p home could be parsed correctly
	 * @return The data of the report, in order for printing
	 */
	virtual auto_ptr<QHaccResultSet> generate( const QString& home,
																						 QString& title,
																						 QString& err,
																						 bool& ok ) =0;
	/**
	 * Create a table with the rows of the report in it (in order
	 * of output). 
	 * @param journalid The id of the journal on which to operate
	 * @param accounts A table of accounts to use to make the report
	 * @param start The start date of the report (inclusive)
	 * @param end The end date of the report (inclusive)
	 * @param title The title of the report
	 * @return The data of the report, in order for printing
	 */
	virtual auto_ptr<QHaccResultSet> generate( uint journalid,
																						 QHaccResultSet * accounts,
																						 const QDate& start,
																						 const QDate&  end,
																						 QString& title ) =0;

	/**
	 * Create a table with the rows of the report in it (in order
	 * of output). 
	 * @param accounts A table of accounts to use to make the report
	 * @param selectors A set of selection criteria to select from each account.
	 * These should use XTRANS constants, and will be added to every call of 
	 * engine->getXTForA()
	 * @param title The title of the report
	 * @return The data of the report, in order for printing
	 */
	virtual auto_ptr<QHaccResultSet> generate( QHaccResultSet * accounts,
																						 vector<TableSelect> selectors,
																						 QString& title ) =0;

	/**
	 * Generate the report from the raw data
	 * @param title The title of the report
	 * @param d The data generated in a generate() call
	 * @return A string of the report
	 */
	virtual QString writereport( const QString& title,
															 const QHaccResultSet * d ) =0;
	
	/**
	 * What should the parent window do when this plugin is selected?
	 * @param start Set the "Start Date" field to this value
	 * @param stop  Set the "End Date" field to this value
	 * @param enableacctsel Enable/Disable the account selector
	 * @param enablemultisel Enable/Disable the account selector multiselection
	 */
	virtual void selected( QDate& start, QDate& stop, bool& enableacctsel,
												 bool& enablemultisel ) =0;
};


class QHaccGraphPlugin : public QHaccPlugin {
 public:
	/**
	 * Initialize the plugin. Call this function before using the plugin
	 */
	virtual void setup( QHacc * eng ) =0;

	virtual void paint( QPainter *, const QRect& ) =0;

	virtual void setData( uint lid, const QHaccResultSet& accts, const QDate& s,
												const QDate& e ) =0;

	virtual vector<TableSelect> describeMouse( const QPoint& ) const =0;
};
#endif
