/* Copyright (c) 2015-2016 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "fts-language.h"
#include "fts-filter-private.h"
#include "fts-common.h"
#include "unichar.h"

static int
fts_filter_contractions_create(const struct fts_language *lang,
			       const char *const *settings,
			       struct fts_filter **filter_r,
			       const char **error_r)
{
	struct fts_filter *filter;

	if (settings[0] != NULL) {
		*error_r = t_strdup_printf("Unknown setting: %s", settings[0]);
		return -1;
	}
	if (strcmp(lang->name, "fr") != 0) {
		*error_r = t_strdup_printf("Unsupported language: %s", lang->name);
		return -1;
	}

	filter = i_new(struct fts_filter, 1);
	*filter = *fts_filter_contractions;
	filter->token = str_new(default_pool, 64);
	*filter_r = filter;
	return 0;
}

static int
fts_filter_contractions_filter(struct fts_filter *filter ATTR_UNUSED,
			    const char **_token,
			    const char **error_r ATTR_UNUSED)
{
	int char_size, pos = 0;
	unichar_t apostrophe;
	const char *token = *_token;

	switch (token[pos]) {
	case 'q':
		pos++;
		if (token[pos] == '\0' || token[pos] != 'u')
			break;
		/* otherwise fall through */
	case 'c':
	case 'd':
	case 'j':
	case 'l':
	case 'm':
	case 'n':
	case 's':
	case 't':
		pos++;
		if (token[pos] == '\0')
			break;
		char_size = uni_utf8_get_char(token + pos, &apostrophe);
		if (IS_APOSTROPHE(apostrophe)) {
			pos += char_size;
			*_token = token + pos;
		}
		if (token[pos] == '\0') /* nothing left */
			return 0;
		break;
	default:
		/* do nothing */
		break;
	}

	return 1;
}

static const struct fts_filter fts_filter_contractions_real = {
	.class_name = "contractions",
	.v = {
		fts_filter_contractions_create,
		fts_filter_contractions_filter,
		NULL
	}
};

const struct fts_filter *fts_filter_contractions = &fts_filter_contractions_real;
