
RANKS* ooiSearch(OOI_NODE* lexicon,unsigned int* wordArray, unsigned int words,int* numResults)
{
INVERTED_INDEX** indexes;
unsigned int* elements;
int found;
unsigned int last_doc_id;
unsigned int i,c, pos;
RANKS* rResults = NULL;
unsigned int rResElem;  /* numero di risultati (valore usato dalla realloc) */

/* rankRes è -1 in caso di errore */
int rankRes;

    *numResults = 0;

    if(words == 0)
        return NULL;

    if(words == 1)
    {
        /* ottimizzazione ricerca per una singola parola */
        pos = ndzLookForWord(lexicon, wordArray[0]);
        
        if(pos == -1 || lexicon[pos].nii <= 0)
            return NULL;

        rResults = NULL;

        last_doc_id = 0;

        /* contatore della posizione attuale nell'array dei risultati */
        rResElem = 0;

        for(i=0; i<lexicon[pos].nii; i++)
            if(lexicon[pos].ii[i].doc_id > 0 &&  lexicon[pos].ii[i].doc_id != last_doc_id )
            {
                last_doc_id = lexicon[pos].ii[i].doc_id;

                /* cerca il documento corrente nella lista dei documenti */
                rankRes = ranksLookForPage(glRanks,lexicon[pos].ii[i].doc_id, nRanks);

                /* se il documento esiste allora è un risultato valido e ha un rank */
                if( rankRes >= 0 )
                {
                    /* primo risultato */
                    if(rResElem==0)
                    {
                        /* inizializza la lista elementi col corrente + l'ultimo documente (page=0) */
                        rResults = malloc(sizeof(RANKS)*2);
                        if(rResults == NULL)
                            return NULL;

                        rResults[0].page = lexicon[pos].ii[i].doc_id;
                        rResults[0].rank = glRanks[rankRes].rank;
                    }
                    else
                    {
                        /* crea una lista col numero attuale di elementi + il corrente + 1 elemento che identifica l'ultimo (page=0) */
                        rResults = realloc(rResults,sizeof(RANKS)*(rResElem+2));
                        if(rResults == NULL)
                            return NULL;

                        rResults[rResElem].page = lexicon[pos].ii[i].doc_id;
                        rResults[rResElem].rank = glRanks[rankRes].rank;
                    }

                    rResElem++;
                }
            }

        /* ultimo elemento identificato con 0 */
        rResults[rResElem].page = 0;
        *numResults = rResElem;

        return rResults;
    }

    /* alloca lo spazio necessario a contenere n puntatori a n indici inversi
       per una verta parola */
    indexes = malloc( sizeof(INVERTED_INDEX)* words);
    elements = malloc( sizeof(unsigned int) * words);

    /* inizializza la variabile che terrà il num. degli elementi */
    rResElem = 0;

    for(i=0; i < words; i++)
    {
        /* cerca la parola nel lexicon*/
        pos = ndzLookForWord(lexicon, wordArray[i]);

        /* se non esiste: esci immediatamante (per ora le ricerche sono in AND
           quindi verranno restituite solo le pagine che contengono tutte le parole) */
        if(pos == -1)
        {
            FREE(indexes);
            FREE(elements);
            return NULL;
        }

        /* copia il puntatore al primo elemento dell'inidce (valori tutti a 0) */
        indexes[i] = lexicon[pos].ii;
        elements[i] = lexicon[pos].nii; /* numero di elementi in questo indice */

        //printf("\nword: %d",wordArray[i]);
        //printII(indexes[i], elements[i]);
    }
    
    /* qui ci troviamo con n indici contenenti la lista dei documenti
       che contengono le n parole cercate */
    /* dobbiamo ritornare solo i documenti che le contengono tutte e n */
    
    /* scorriamo il primo indice e cerchiamo negli altri rimanenti che 
       per ogni documento presente nel primo sia presente anche negli altri */

    /* usa questo codice per non cercare su documenti già visti */
    last_doc_id = 0;

    for(i=0;i<elements[0];i++)
    {
        if( indexes[0][i].doc_id > 0 && indexes[0][i].doc_id!=last_doc_id) /* documento valido */
        {

            /* setta last_doc_id con l'attuale doc_id per evitare di cercare ancora
               in questo documento (solo con array ordinato) */
            last_doc_id = indexes[0][i].doc_id;

            /* prendiamo per default che il documento sia presente
               nel primo indice in cui non viene trovato viene messo a 0 */
            found = 1;

            /* cerca questo documento (indexes[0][i]) negli altri indici */
            /* cicla in tutti gli indici a partire dal primo */
            for(c = 1; c < words; c++)
            {
                if( iiLookForDocId(indexes[c], indexes[0][i].doc_id, elements[c]) == -1)
                {
                    found = 0;
                    break;    /* in questo indice non c'è il documento: esci dal ciclo */
                }

            }
            /* fine for 2*/
            
            if(found == 1)
            {
                //printf(" - pageID: %i\n",indexes[0][i].doc_id);
                /* cerca il documento corrente nella lista dei documenti */
                rankRes = ranksLookForPage(glRanks,indexes[0][i].doc_id /*lexicon[0].ii[i].doc_id*/, nRanks);
                /* se il documento esiste allora è un risultato valido e ha un rank */
                if( rankRes >= 0 )
                {
                    /* primo risultato */
                    if(rResElem==0)
                    {
                        /* inizializza la lista elementi col corrente + l'ultimo documente (page=0) */
                        rResults = malloc(sizeof(RANKS)*2);
                        if(rResults == NULL)
                        {
                            FREE(indexes);
                            FREE(elements);
                        return NULL;
                        }

                        rResults[0].page = indexes[0][i].doc_id;
                        rResults[0].rank = glRanks[rankRes].rank;
                    }
                    else
                    {
                        /* crea una lista col numero attuale di elementi + il corrente + 1 elemento che identifica l'ultimo (page=0) */
                        rResults = realloc(rResults,sizeof(RANKS)*(rResElem+2));
                        if(rResults == NULL)
                        {
                            FREE(indexes);
                            FREE(elements);
                        return NULL;
                        }

                        rResults[rResElem].page = indexes[0][i].doc_id;
                        rResults[rResElem].rank = glRanks[rankRes].rank;
                    }
                    
                    rResElem++;
                }
            }

        }
        /* fine if 1 */
    }
    /* fine for 1*/
    

    /* arriviamo qui solo per query di + di 1 parola */

    /* ultimo documento */
    if(rResults)
        rResults[rResElem].page = 0;

    /* libera la memoria allocata */
    FREE(indexes);
    FREE(elements);

    *numResults = rResElem;

    return rResults;
}

/* ritorna la posizione o -1 in caso di nessuno slot libero */
int GetFreeQuerySlot()
{
int i;
    
    for(i=0;i<MAXPARRSEARCH;i++)
    {
        if(queryStt[i].available == 1)
            return i;
    }

return -1;
}

/* ritorna 1 o 0 in caso di query correntemente in esecuzione */
int ActiveQuery()
{
int i;
    
    for(i=0;i<MAXPARRSEARCH;i++)
    {
        /* c'è almeno una query: ritorna true */
        if(queryStt[i].available == 0)
            return 1;
    }

/* nessuna query*/
return 0;
}

/* ritorna la posizione o -1 in caso di nessuno slot con la query cercata */
int GetQuerySlotByText(unsigned int* queryArray, unsigned int n)
{
int i;
    
    for(i=0;i<MAXPARRSEARCH;i++)
    {
        if(queryStt[i].available == 0 && CheckUIntArray(queryArray, n, queryStt[i].queryArray, queryStt[i].nWords)==1 )
            return i;
    }

return -1;
}

/* ritorna la posizione o -1 in caso di nessuno slot con la query cercata */
int GetQuerySlotByTextQuery(char* text_query)
{
int i;
    
    for(i=0;i<MAXPARRSEARCH;i++)
    {
		if( queryStt[i].available == 0 && strcmp(text_query, queryStt[i].text_query) ==0 )
            return i;
    }

return -1;
}


RANKS* mysqlSearch(char* text_query , int* numResults)
{
RANKS* rResults = NULL;

MYSQL_RES gRes;
MYSQL_RES** tmpRes=NULL;
MYSQL_ROW row;
char* sqlQuery;

unsigned int counter;

	/* mysql non connesso */
	if( bIsMySQLConnected == 0 )
		return NULL;

	sqlQuery = malloc( MAXQUERYSIZE + 200 );
	snprintf_mysql_escaped_sql_statement(&glMysql, sqlQuery, MAXQUERYSIZE + 200, "select id,rank from pagelist where match(title,text,hostname,page) against(\'%s\' in boolean mode) ORDER BY rank DESC LIMIT 1000",text_query,text_query,text_query);

	tmpRes=(MYSQL_RES**)malloc(sizeof(MYSQL_RES));

	my_mysql_query_and_store_results(&glMysql,sqlQuery,tmpRes,&gRes);

	FREE(sqlQuery);

	*numResults = mysql_affected_rows(&glMysql);
	
	/* TODO: gestione errore nella query ( o sconnessione dal DB ) */
	
	rResults = malloc( sizeof(RANKS) * ( (*numResults) + 1) );

	if(rResults == NULL)
	{
		if(*tmpRes)
		{
			mysql_free_result(*tmpRes);
		}
			
		FREE(tmpRes);

		return NULL;
	}

	counter = 0;

	while( (row = mysql_fetch_row(&gRes)) )
	{

		rResults[counter].page = atoi(row[0]);
		rResults[counter].rank = atoi(row[1]);

		counter++;
	}

	/* ultimo documento */
    if(rResults)
        rResults[counter].page = 0;
	
	if(*tmpRes)
	{
		mysql_free_result(*tmpRes);
	}
	FREE(tmpRes);

return rResults;
}
