#include <string.h>

#include "common.h"

unsigned long int masklist[ALPHABET_SIZE];
unsigned char *pattern;
size_t pattern_len;


void shiftand_aprox_preprocess_pattern(const unsigned char* pat)
{
	int i = 0;

	pattern = strcpy_alloc(&pattern,pat);
	
        pattern_len  = strlen(pattern);
	for (i = 0; i < ALPHABET_SIZE; i++){
		masklist[i] = 0;
	}
	for (i = 0; i < pattern_len; i++){
		masklist[pattern[i]] |= 1<< (pattern_len -1 - i);
	}

}

int shiftand_aprox_find(const unsigned char* text, unsigned int k)
{
	int text_len = 0;
	int i = 0;		/* Posição do cursor  em texto */
	int j = 0;
	unsigned long int *R;	/* Os registradores... */
	unsigned long int initial_state = 0;	/* Guarda a mascara para o estado inicial */
	unsigned long int Rold, Rnew;
	
        text_len = strlen(text);
        if (pattern_len > text_len){
		return ERROR;
	}

	if (k == 0){
		shiftand_exato_preprocess_pattern(pattern);
		return shiftand_exato_find(text,0);
	} 
	
	initial_state = 1 << (pattern_len -1);

	/* Set-up registers */
	R=alloc_registers(&R,k+1);
	R[0] = 0x0;
	R[1] = 0x1 << (pattern_len -1);
	for (j = 2; j <= k; j++){
		R[j] = ( R[j-1] |(R[j-1]>>1));
	}
	
	/* A procura propriamente dita*/
	while (i < text_len){
		Rold = R[0];
		Rnew = ((Rold>>1)|initial_state) & masklist[text[i]];
		R[0] = Rnew;

		for (j = 1; j <= k ; j++){
			Rnew = (R[j]>>1 & masklist[text[i]])|Rold|((Rold|Rnew)>>1)|initial_state;
			Rold = R[j];
			R[j] = Rnew;
		}
		
		if (Rnew&1){
			return i;
		}
		i++; 
	}
	return NOT_FOUND;
}
