//
// (C) Copyright 2011-2012 Sergey A. Babkin.
// This file is a part of Triceps.
// See the file COPYRIGHT for the copyright notice and license information
//
// The encapsulation of Perl compare function for the sorted index.

// Include TricepsPerl.h and PerlCallback.h before this one.

// ###################################################################################

#ifndef __TricepsPerl_PerlSortCondition_h__
#define __TricepsPerl_PerlSortCondition_h__

#include <common/Conf.h>
#include <type/SortedIndexType.h>

using namespace TRICEPS_NS;

namespace TRICEPS_NS
{
namespace TricepsPerl 
{

class PerlSortCondition : public SortedIndexCondition
{
public:
	// @param sortName - name of the sort, for the messages about fatal errors in cmparator
	// @param cbInit - callback that runs at the type initialization time, may be NULL, may be
	//        used to check that the args make sense and generate the compare callback on the fly.
	//        Args: TableType tabt, IndexType idxt, RowType rowt
	//          tabt - table type that performs the initialization
	//          idxt - link back to the index type that contains the condition (used to
	//                 set the compare callback and such)
	//          rowt - row type of the table, passed directly as a convenience
	//        Returns undef on success or an error message (may freely contain \n) on error.
	// @param cbCompare - callback that compares two rows. May be NULL, but in this case has
	//        to be generated by the initialize callback; having it still NULL after initialization
	//        is an error.
	//        Args: Row r1, Row r2.
	//        Returns the result of r1 <=> r2.
	PerlSortCondition(const char *sortName, Onceref<PerlCallback> cbInit, 
		Onceref<PerlCallback> cbCompare);
	// always makes an uninitialized copy!
	PerlSortCondition(const PerlSortCondition &other);
	~PerlSortCondition();

	// base class methods
	virtual bool equals(const SortedIndexCondition *sc) const;
	virtual bool match(const SortedIndexCondition *sc) const;
	virtual void printTo(string &res, const string &indent = "", const string &subindent = "  ") const;
	virtual SortedIndexCondition *copy() const;
	virtual bool operator() (const RowHandle *r1, const RowHandle *r2) const;
	virtual void initialize(Erref &errors, TableType *tabtype, SortedIndexType *indtype);

	// Set the comparator, could be called from the initializer.
	// It is technically possible to have the initialization called
	// from multiple threads, but don't do that!
	// @return - true on success, false if the object is already initialized
	bool setComparator(Onceref<PerlCallback> cbComparator);

protected:
	// Initialization: may be used to dynamically generate a comparator.
	// The args are: indexType (self), rowType.
	// On success returns undef, on failure an error message.
	Autoref<PerlCallback> cbInitialize_; 

	// Comparison called from operator().
	// The args are: rh1, rh2, rowType.
	// The Perl callback returns the result of (rh1 <=> rh2).
	Autoref<PerlCallback> cbCompare_; 

	bool initialized_; // flag: this object has been initialized
	SV *svRowType_; // avoid creating the row type object on each comparison, cache it
	TableType *tabType_; // remembered for error messages, NOT a reference!
	string name_; // name of the sort for error messages on fatal errors in comparator
};

}; // Triceps::TricepsPerl
}; // Triceps

using namespace TRICEPS_NS::TricepsPerl;

#endif // __TricepsPerl_PerlSortCondition_h__
