/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


#include <dddataquery.h>
#include <dddatatable.h>
#include <dditem.h>
#include <ddwebcgi.h>


/**
	Default Constructor.
*/

dddataquery::dddataquery()
{

}


/**
	Standard Constructor.
*/

dddataquery::dddataquery( const ddstring& name, const ddstring& querystring )
:	ddbasename( name )
{
	set_query_string( querystring );
}


/**
	Destructor. Tut nix.
*/

dddataquery::~dddataquery()
{

}


/**
	Die Query-Parameter resetten
*/

void dddataquery::clear_query_data()
{
	for( size_t i=0; i<size(); ++i )
	{
		if( !_data[i]->get_name().empty() )
			_data[i]->clear_value();
	}
}


/**
	Übergibt den wert des x.ten parameters. Dazu muss erst der tatsächliche, interne 
	index des entsprechenden query items rausgefunden werden.
	Bsp: select * from tr_message where id  = {id};
	Der interne index ist 1, der parameter-index ist 0.
*/

void dddataquery::set_query_parameter( size_t index, const ddstring& param )
{
	
	if( param.empty() )
		return;
	
	if( --index >= _indexpositions.size() )
		log_fatal( "dddataquery::set_query_parameter: " + get_name() + ":Zu viele Parameter! out of range: " + param + " (index: " + ddstrutil::from_size_t( index ) + ")" );
	
	// thats it
	_data[ _indexpositions[index] ]->operator=( param );
	
	/* 
	
	FIX! SUPER GEILER BRAINFUCK BROWN PAPERBAG BUG
	
	das hier soll den n. _unterschiedlichen_ query-parameter finden, 
	findet aber ggf. wieder den n. _gleichen_, falls der parameter mehrmals
	eingesetzt wird... geil. siehe:
	
		pager_postbox = "select *, {id} sn_margin, DATE_FORMAT( sn_datecreated,'%d.%m.%Y %k:%i') 'sn_date'
  			from users.tr_pager_xx 
  	 		where (id_sender='{id}' and flag_visible_for_sender = 1 and id_receiver='{id_contact}' ) or
    			    (id_receiver='{id}' and flag_visible_for_receiver = 1 and id_sender='{id_contact}' )  
					order by sn_datecreated desc";
	
	if( param.empty() )
		return;
	
	size_t cnt = 0;
	size_t idx = 0;
	// Parameter-Eintrag 'index' suchen
	for( ; idx<size(); ++idx )
	{
		const ddstring& name = _data[idx]->get_name();
		if( !name.empty() )
		{
			// Param-Eintrag gefunden ...
			cnt++;
			// Ist es der richtige ?
			if( cnt == index )
				break;
		}
		
	}

	// Wurde überhaupt was gefunden?
	if( idx < size() )
	{
		cout << "AHA: index:" << index << " idx:" << idx << " name:" << _data[idx]->get_name() << " param:" << param << endl;
		_data[idx]->operator=( param );
	}
	else
	{
		log_fatal( "dddataquery::set_query_parameter: " + get_name() + ": not found: " + param + " (index: " + ddstrutil::from_size_t( index ) );
	}
	
	*/
	
	
	
}


/**
	CGI daten in die entsprechenden query-parameter laden.
	@see ddwebcgi
*/

void dddataquery::set_query_data( ddwebcgi& cgi )
{
	const ddmapindex& index = get_index();
	ddmapindex::const_iterator pos = index.begin();
	
	for( ; pos != index.end(); ++pos )
	{
		
		/*
			über alle form felder, falls das feld _auch_
			im cgi vorhanden dann die daten übernehmen.
			NEU: anderfalls das formfeld löschen
			NEU: Nein, doch nicht
		*/
		
		ddwebcgi::iterator pos2 = cgi.find( (*pos).first );
    if( pos2 != cgi.end() )
			_data[(*pos).second]->operator=( (*pos2).second );		
		//else
		//	_data[(*pos).second]->clear_value();
		
	}
}


/**
	Den Query-String parsen.
*/

void dddataquery::set_query_string( const ddstring& src )
{

	_rawquerystring = src; 
	
	ddstring::size_type beg=0, end1=0, end2=0, end3=0;
	
	while ( beg < src.size() )
	{
		end1 = src.find( '{', beg );
		// anfang gefunden -> ende suchen
		if( end1 != ddstring::npos )
		{
			// Fülleintrag
			add( new dddataqueryitem( src.substr( beg, end1-beg ) ) );
			end2 = end1+1;
			end3 = src.find( '}', end2 );
			if( end3 != ddstring::npos  )	// ende auch gefunden.
			{
				add_child( src.substr( end2, end3-end2 ) );   //(value)
				beg = end3+1;
			}
			else		// ende nicht gefunden
			{
				return;
			}
		}
		// anfang nicht gefunden
		else
		{
			// Fülleintrag
			add( new dddataqueryitem( src.substr( beg ) ) );
			break;        
		}

	} // while
	
}


/**
	Eine Parameter-Eintrag erzeugen.
*/

void dddataquery::add_child( const ddstring& name )
{
	// hack: the name might contain a default value.
	ddstring namepart = name;
	ddstring defpart;
	size_t dot = name.rfind( ':' );
	if( dot != ddstring::npos )
	{
		namepart = name.substr( 0, dot );
		defpart  = name.substr( dot+1 );// fix!default!!!
	}
	
	// siehe brown paperbag bug: weil das auffinden der parameter per
	// positions nicht funktioniert, speichern wir diese in einem
	// zusätzlichen vector:
	//
	// also:
	// select * from moo where bla='{id1}' or moo='{id2}'
	//
	// _mapindex['id1'] = 1
	// _mapindex['id2'] = 3
	//
	// ensprechend
	//
	// _indexpositions[0] = 1
	// _indexpositions[1] = 3
	//
	// damit können die parameter direkt per index ohne keys
	// übergeben werden.
	//
	// FIX!
	// Das sollte für alle multimaps gelten.
	
	bool already_there = _index.contains_key( namepart );
	size_t idx = add_by_key( namepart, new dddataqueryitem( namepart, defpart ) );
	
	// nur anhängen, falls neu, das ist der trick
	if( !already_there )
		_indexpositions.push_back( idx );
		
}



