/*
 * Copyright (C) 2012 - Juan Ferrer Toribio
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

#ifndef DB_ITERATOR_H
#define DB_ITERATOR_H

#include "db-model.h"

#define DB_TYPE_ITERATOR			(db_iterator_get_type ())
#define DB_ITERATOR(obj)			(G_TYPE_CHECK_INSTANCE_CAST (obj, DB_TYPE_ITERATOR, DbIterator))
#define DB_IS_ITERATOR(obj)			(G_TYPE_CHECK_INSTANCE_TYPE (obj, DB_TYPE_ITERATOR))
#define DB_ITERATOR_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST (klass, DB_TYPE_ITERATOR, DbIteratorClass))
#define DB_IS_ITERATOR_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE (klass, DB_TYPE_ITERATOR))
#define DB_ITERATOR_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS (obj, DB_TYPE_ITERATOR, DbIteratorClass))

#define DB_TYPE_ITERATOR_MODE		(db_iterator_mode_get_type ())

typedef struct _DbIterator DbIterator;
typedef struct _DbIteratorClass DbIteratorClass;

#include "db-param.h"

/**
 * DbIteratorMode:
 * @DB_ITERATOR_MODE_ON_CHANGE: every change made in a cell will be sent to the
 * database instantly.
 * @DB_ITERATOR_MODE_ON_ITER: every change made in a row will be sent to the
 * database when iter changes.
 * @DB_ITERATOR_MODE_ON_DEMAND: nothing will be sent to the database since it's
 * demanded.
 * 
 * The working mode of a Iterator.
 **/
typedef enum
{
	 DB_ITERATOR_MODE_ON_CHANGE
	,DB_ITERATOR_MODE_ON_ITER
	,DB_ITERATOR_MODE_ON_DEMAND
}
DbIteratorMode;

/**
 * DbIteratorMove:
 * @DB_ITERATOR_MOVE_FIRST: Moves to the first position.
 * @DB_ITERATOR_MOVE_PREVIOUS: Moves previous.
 * @DB_ITERATOR_MOVE_NEXT: Moves next.
 * @DB_ITERATOR_MOVE_LAST: Moves to the last position.
 * 
 * Indicates the movement.
 **/
typedef enum
{
	 DB_ITERATOR_MOVE_FIRST
	,DB_ITERATOR_MOVE_PREVIOUS
	,DB_ITERATOR_MOVE_NEXT
	,DB_ITERATOR_MOVE_LAST
}
DbIteratorMove;

struct _DbIterator
{
	GObject parent;
	DbModel * model;
	GList * params;
	DbIteratorMode mode;
	DbIter iter;
	gint row;
	gboolean row_selected;
	gboolean remember_selection;
	
	DbConn * conn;
	SqlStmt * stmt;
	gchar * sql;
	gboolean use_file;
};

struct _DbIteratorClass
{
	/* <private> */
	GObjectClass parent;
};

GType					db_iterator_get_type				();
GType					db_iterator_mode_get_type			() G_GNUC_CONST;

DbIterator *			db_iterator_new						(DbModel * model);
DbIterator *			db_iterator_new_with_stmt			(DbConn * conn, SqlStmt * stmt);
DbIterator *			db_iterator_new_with_sql			(DbConn * conn, const gchar * sql);
DbModel *				db_iterator_get_model				(DbIterator * obj);
DbConn *				db_iterator_get_conn				(DbIterator * obj);
void					db_iterator_set_conn				(DbIterator * obj, DbConn * conn);
gboolean				db_iterator_is_ready				(DbIterator * obj);
DbIteratorMode			db_iterator_get_mode				(DbIterator * obj);
void					db_iterator_set_mode				(DbIterator * obj, DbIteratorMode mode);
gint					db_iterator_get_row					(DbIterator * obj);
gboolean				db_iterator_get_iter				(DbIterator * obj, DbIter * iter);
void					db_iterator_move_iter				(DbIterator * obj, DbIter * iter);
void					db_iterator_move_first				(DbIterator * obj);
void					db_iterator_move_last				(DbIterator * obj);
void					db_iterator_move_previous			(DbIterator * obj);
void					db_iterator_move_next				(DbIterator * obj);
void					db_iterator_move_to					(DbIterator * obj, DbIteratorMove move);
void					db_iterator_refresh					(DbIterator * obj);
const GvnParamSpec *	db_iterator_get_spec				(DbIterator * obj, gint column);
const GValue *			db_iterator_get_value				(DbIterator * obj, gint column);
gint					db_iterator_get_column_index		(DbIterator * obj, const gchar * name);
void					db_iterator_set_value				(DbIterator * obj, gint column, const GValue * value, GError ** err);
void					db_iterator_delete					(DbIterator * obj);
void					db_iterator_insert					(DbIterator * obj);
void					db_iterator_add_param				(DbIterator * obj, DbParam * param);
GvnParam *				db_iterator_get_param				(DbIterator * obj, const gchar * column);
GList *					db_iterator_get_params				(DbIterator * obj);
void					db_iterator_bind_param				(DbIterator * obj, const gchar * column, GvnParam * param);
void					db_iterator_link					(DbIterator * obj, const gchar * field, DbIterator * src, const gchar * column);
void					db_iterator_link_with_param			(DbIterator * obj, const gchar * field, GvnParam * param);
gint					db_iterator_get_nrows				(DbIterator * obj);
DbModelUpdateFlags		db_iterator_get_update_flags		(DbIterator * obj);
void					db_iterator_reverse_operations		(DbIterator * obj);
void					db_iterator_perform_operations		(DbIterator * obj);
DbModelRowOp			db_iterator_get_pending_operations	(DbIterator * obj);
gboolean				db_iterator_has_pending_operations	(DbIterator * obj);

#endif