/*
 * fontconfig/test/test-conf.c
 *
 * Copyright © 2000 Keith Packard
 * Copyright © 2018 Akira TAGOH
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the author(s) not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  The authors make no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
#include <stdio.h>
#include <string.h>
#include <fontconfig/fontconfig.h>
#include <json.h>

struct _FcConfig {
    FcStrSet	*configDirs;	    /* directories to scan for fonts */
    FcStrSet    *configMapDirs;
    FcStrSet	*fontDirs;
    FcStrSet	*cacheDirs;
    FcStrSet	*configFiles;	    /* config files loaded */
    void	*subst[FcMatchKindEnd];
    int		maxObjects;	    /* maximum number of tests in all substs */
    FcStrSet	*acceptGlobs;
    FcStrSet	*rejectGlobs;
    FcFontSet	*acceptPatterns;
    FcFontSet	*rejectPatterns;
    FcFontSet	*fonts[FcSetApplication + 1];
};

static FcPattern *
build_pattern (json_object *obj)
{
    json_object_iter iter;
    FcPattern *pat = FcPatternCreate ();

    json_object_object_foreachC (obj, iter)
    {
	FcValue v;
	FcBool destroy_v = FcFalse;
	FcMatrix matrix;

	if (json_object_get_type (iter.val) == json_type_boolean)
	{
	    v.type = FcTypeBool;
	    v.u.b = json_object_get_boolean (iter.val);
	}
	else if (json_object_get_type (iter.val) == json_type_double)
	{
	    v.type = FcTypeDouble;
	    v.u.d = json_object_get_double (iter.val);
	}
	else if (json_object_get_type (iter.val) == json_type_int)
	{
	    v.type = FcTypeInteger;
	    v.u.i = json_object_get_int (iter.val);
	}
	else if (json_object_get_type (iter.val) == json_type_string)
	{
	    const FcObjectType *o = FcNameGetObjectType (iter.key);
	    if (o && (o->type == FcTypeRange || o->type == FcTypeDouble || o->type == FcTypeInteger))
	    {
		const FcConstant *c = FcNameGetConstant ((const FcChar8 *) json_object_get_string (iter.val));
		if (!c) {
		    fprintf (stderr, "E: value is not a known constant\n");
		    fprintf (stderr, "   key: %s\n", iter.key);
		    fprintf (stderr, "   val: %s\n", json_object_get_string (iter.val));
		    continue;
		}
		if (strcmp (c->object, iter.key) != 0)
		{
		    fprintf (stderr, "E: value is a constant of different object\n");
		    fprintf (stderr, "   key: %s\n", iter.key);
		    fprintf (stderr, "   val: %s\n", json_object_get_string (iter.val));
		    fprintf (stderr, "   key implied by value: %s\n", c->object);
		    continue;
		}
		v.type = FcTypeInteger;
		v.u.i = c->value;
	    }
	    else if (strcmp (json_object_get_string (iter.val), "DontCare") == 0)
	    {
		v.type = FcTypeBool;
		v.u.b = FcDontCare;
	    }
	    else
	    {
		v.type = FcTypeString;
		v.u.s = (const FcChar8 *) json_object_get_string (iter.val);
	    }
	}
	else if (json_object_get_type (iter.val) == json_type_null)
	{
	    v.type = FcTypeVoid;
	}
	else if (json_object_get_type (iter.val) == json_type_array)
	{
	    json_object *o;
	    json_type type;
	    int i, n;

	    n = json_object_array_length (iter.val);
	    if (n == 0) {
		fprintf (stderr, "E: value is an empty array\n");
		continue;
	    }

	    o = json_object_array_get_idx (iter.val, 0);
	    type = json_object_get_type (o);
	    if (type == json_type_string) {
		const FcObjectType *fc_o = FcNameGetObjectType (iter.key);
		if (fc_o && fc_o->type == FcTypeCharSet) {
		    FcCharSet* cs = FcCharSetCreate ();
		    if (!cs) {
			fprintf (stderr, "E: failed to create charset\n");
			continue;
		    }
		    v.type = FcTypeCharSet;
		    v.u.c = cs;
		    destroy_v = FcTrue;
		    for (i = 0; i < n; i++)
	            {
			const FcChar8 *src;
			int len, nchar, wchar;
			FcBool valid;
			FcChar32 dst;

			o = json_object_array_get_idx (iter.val, i);
			type = json_object_get_type (o);
			if (type != json_type_string) {
			    fprintf (stderr, "E: charset value not string\n");
			    FcValueDestroy (v);
			    continue;
			}
			src = (const FcChar8 *) json_object_get_string (o);
			len = json_object_get_string_len (o);
			valid = FcUtf8Len (src, len, &nchar, &wchar);
			if (valid == FcFalse) {
			    fprintf (stderr, "E: charset entry not well formed\n");
			    FcValueDestroy (v);
			    continue;
			}
			if (nchar != 1) {
			    fprintf (stderr, "E: charset entry not not one codepoint\n");
			    FcValueDestroy (v);
			    continue;
			}
			FcUtf8ToUcs4 (src, &dst, len);
			if (FcCharSetAddChar (cs, dst) == FcFalse) {
			    fprintf (stderr, "E: failed to add to charset\n");
			    FcValueDestroy (v);
			    continue;
			}
		    }
		} else {
		    FcLangSet* ls = FcLangSetCreate ();
		    if (!ls) {
			fprintf (stderr, "E: failed to create langset\n");
			continue;
		    }
		    v.type = FcTypeLangSet;
		    v.u.l = ls;
		    destroy_v = FcTrue;
		    for (i = 0; i < n; i++)
	            {
			o = json_object_array_get_idx (iter.val, i);
			type = json_object_get_type (o);
			if (type != json_type_string) {
			    fprintf (stderr, "E: langset value not string\n");
			    FcValueDestroy (v);
			    continue;
			}
			if (FcLangSetAdd (ls, (const FcChar8 *)json_object_get_string (o)) == FcFalse) {
			    fprintf (stderr, "E: failed to add to langset\n");
			    FcValueDestroy (v);
			    continue;
			}
		    }
		}
	    } else if (type == json_type_double || type == json_type_int) {
		double values[4];
		if (n != 2 && n != 4) {
		    fprintf (stderr, "E: array starting with number not range or matrix\n");
		    continue;
		}
		for (i = 0; i < n; i++) {
		    o = json_object_array_get_idx (iter.val, i);
		    type = json_object_get_type (o);
		    if (type != json_type_double && type != json_type_int) {
			fprintf (stderr, "E: numeric array entry not a number\n");
			continue;
		    }
		    values[i] = json_object_get_double (o);
		}
		if (n == 2) {
		    v.type = FcTypeRange;
		    v.u.r = FcRangeCreateDouble (values[0], values[1]);
		    if (!v.u.r) {
			fprintf (stderr, "E: failed to create range\n");
			continue;
		    }
		    destroy_v = FcTrue;
		} else {
		    v.type = FcTypeMatrix;
		    v.u.m = &matrix;
		    matrix.xx = values[0];
		    matrix.xy = values[1];
		    matrix.yx = values[2];
		    matrix.yy = values[3];
		}
	    } else {
		fprintf (stderr, "E: array format not recognized\n");
		continue;
	    }
	}
	else
	{
	    fprintf (stderr, "W: unexpected object to build a pattern: (%s %s)", iter.key, json_type_to_name (json_object_get_type (iter.val)));
	    continue;
	}
	FcPatternAdd (pat, iter.key, v, FcTrue);
	if (destroy_v)
	    FcValueDestroy (v);
    }
    return pat;
}

static FcFontSet *
build_fs (json_object *obj)
{
    FcFontSet *fs = FcFontSetCreate ();
    int i, n;

    n = json_object_array_length (obj);
    for (i = 0; i < n; i++)
    {
	json_object *o = json_object_array_get_idx (obj, i);
	FcPattern *pat;

	if (json_object_get_type (o) != json_type_object)
	    continue;
	pat = build_pattern (o);
	FcFontSetAdd (fs, pat);
    }

    return fs;
}

static FcBool
build_fonts (FcConfig *config, json_object *root)
{
    json_object *fonts;
    FcFontSet *fs;

    if (!json_object_object_get_ex (root, "fonts", &fonts) ||
	json_object_get_type (fonts) != json_type_array)
    {
	fprintf (stderr, "W: No fonts defined\n");
	return FcFalse;
    }
    fs = build_fs (fonts);
    /* FcConfigSetFonts (config, fs, FcSetSystem); */
    if (config->fonts[FcSetSystem])
	FcFontSetDestroy (config->fonts[FcSetSystem]);
    config->fonts[FcSetSystem] = fs;

    return FcTrue;
}

static FcBool
run_test (FcConfig *config, json_object *root)
{
    json_object *tests;
    int i, n, fail = 0;

    if (!json_object_object_get_ex (root, "tests", &tests) ||
	json_object_get_type (tests) != json_type_array)
    {
	fprintf (stderr, "W: No test cases defined\n");
	return FcFalse;
    }
    n = json_object_array_length (tests);
    for (i = 0; i < n; i++)
    {
	json_object *obj = json_object_array_get_idx (tests, i);
	json_object_iter iter;
	FcPattern *query = NULL;
	FcPattern *result = NULL;
	FcFontSet *result_fs = NULL;
	const char *method = NULL;

	if (json_object_get_type (obj) != json_type_object)
	    continue;
	json_object_object_foreachC (obj, iter)
	{
	    if (strcmp (iter.key, "method") == 0)
	    {
		if (json_object_get_type (iter.val) != json_type_string)
		{
		    fprintf (stderr, "W: invalid type of method: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
		    continue;
		}
		method = json_object_get_string (iter.val);
	    }
	    else if (strcmp (iter.key, "query") == 0)
	    {
		if (json_object_get_type (iter.val) != json_type_object)
		{
		    fprintf (stderr, "W: invalid type of query: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
		    continue;
		}
		if (query)
		    FcPatternDestroy (query);
		query = build_pattern (iter.val);
	    }
	    else if (strcmp (iter.key, "result") == 0)
	    {
		if (json_object_get_type (iter.val) != json_type_object)
		{
		    fprintf (stderr, "W: invalid type of result: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
		    continue;
		}
		if (result)
		    FcPatternDestroy (result);
		result = build_pattern (iter.val);
	    }
	    else if (strcmp (iter.key, "result_fs") == 0)
	    {
		if (json_object_get_type (iter.val) != json_type_array)
		{
		    fprintf (stderr, "W: invalid type of result_fs: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
		    continue;
		}
		if (result_fs)
		    FcFontSetDestroy (result_fs);
		result_fs = build_fs (iter.val);
	    }
	    else
	    {
		fprintf (stderr, "W: unknown object: %s\n", iter.key);
	    }
	}
	if (method != NULL && strcmp (method, "match") == 0)
	{
	    FcPattern *match;
	    FcResult res;

	    if (!query)
	    {
		fprintf (stderr, "E: no query defined.\n");
		fail++;
		goto bail;
	    }
	    if (!result)
	    {
		fprintf (stderr, "E: no result defined.\n");
		fail++;
		goto bail;
	    }
	    FcConfigSubstitute (config, query, FcMatchPattern);
	    FcDefaultSubstitute (query);
	    match = FcFontMatch (config, query, &res);
	    if (match)
	    {
		FcPatternIter iter;
		int x, vc;

		FcPatternIterStart (result, &iter);
		do
		{
		    vc = FcPatternIterValueCount (result, &iter);
		    for (x = 0; x < vc; x++)
		    {
			FcValue vr, vm;

			if (FcPatternIterGetValue (result, &iter, x, &vr, NULL) != FcResultMatch)
			{
			    fprintf (stderr, "E: unable to obtain a value from the expected result\n");
			    fail++;
			    goto bail;
			}
			if (FcPatternGet (match, FcPatternIterGetObject (result, &iter), x, &vm) != FcResultMatch)
			{
			    vm.type = FcTypeVoid;
			}
			if (!FcValueEqual (vm, vr))
			{
			    printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result, &iter));
			    printf ("   actual result:");
			    FcValuePrint (vm);
			    printf ("\n   expected result:");
			    FcValuePrint (vr);
			    printf ("\n");
			    fail++;
			    goto bail;
			}
		    }
		} while (FcPatternIterNext (result, &iter));
	    bail:
		FcPatternDestroy (match);
	    }
	    else
	    {
		fprintf (stderr, "E: no match\n");
		fail++;
	    }
	}
	else if (method != NULL && strcmp (method, "list") == 0)
	{
	    FcFontSet *fs;

	    if (!query)
	    {
		fprintf (stderr, "E: no query defined.\n");
		fail++;
		goto bail2;
	    }
	    if (!result_fs)
	    {
		fprintf (stderr, "E: no result_fs defined.\n");
		fail++;
		goto bail2;
	    }
	    fs = FcFontList (config, query, NULL);
	    if (!fs)
	    {
		fprintf (stderr, "E: failed on FcFontList\n");
		fail++;
	    }
	    else
	    {
		int i;

		if (fs->nfont != result_fs->nfont)
		{
		    printf ("E: The number of results is different:\n");
		    printf ("   actual result: %d\n", fs->nfont);
		    printf ("   expected result: %d\n", result_fs->nfont);
		    fail++;
		    goto bail2;
		}
		for (i = 0; i < fs->nfont; i++)
		{
		    FcPatternIter iter;
		    int x, vc;

		    FcPatternIterStart (result_fs->fonts[i], &iter);
		    do
		    {
			vc = FcPatternIterValueCount (result_fs->fonts[i], &iter);
			for (x = 0; x < vc; x++)
			{
			    FcValue vr, vm;

			    if (FcPatternIterGetValue (result_fs->fonts[i], &iter, x, &vr, NULL) != FcResultMatch)
			    {
				fprintf (stderr, "E: unable to obtain a value from the expected result\n");
				fail++;
				goto bail2;
			    }
			    if (FcPatternGet (fs->fonts[i], FcPatternIterGetObject (result_fs->fonts[i], &iter), x, &vm) != FcResultMatch)
			    {
				vm.type = FcTypeVoid;
			    }
			    if (!FcValueEqual (vm, vr))
			    {
				printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result_fs->fonts[i], &iter));
				printf ("   actual result:");
				FcValuePrint (vm);
				printf ("\n   expected result:");
				FcValuePrint (vr);
				printf ("\n");
				fail++;
				goto bail2;
			    }
			}
		    } while (FcPatternIterNext (result_fs->fonts[i], &iter));
		}
	    bail2:
		FcFontSetDestroy (fs);
	    }
	}
	else
	{
	    fprintf (stderr, "W: unknown testing method: %s\n", method);
	}
	if (method)
	    method = NULL;
	if (result)
	{
	    FcPatternDestroy (result);
	    result = NULL;
	}
	if (result_fs)
	{
	    FcFontSetDestroy (result_fs);
	    result_fs = NULL;
	}
	if (query)
	{
	    FcPatternDestroy (query);
	    query = NULL;
	}
    }

    return fail == 0;
}

static FcBool
run_scenario (FcConfig *config, char *file)
{
    FcBool ret = FcTrue;
    json_object *root, *scenario;

    root = json_object_from_file (file);
    if (!root)
    {
	fprintf (stderr, "E: Unable to read the file: %s\n", file);
	return FcFalse;
    }
    if (!build_fonts (config, root))
    {
	ret = FcFalse;
	goto bail1;
    }
    if (!run_test (config, root))
    {
	ret = FcFalse;
	goto bail1;
    }

bail1:
    json_object_put (root);

    return ret;
}

static FcBool
load_config (FcConfig *config, char *file)
{
    FILE *fp;
    long len;
    char *buf = NULL;
    FcBool ret = FcTrue;

    if ((fp = fopen(file, "rb")) == NULL)
	return FcFalse;
    fseek (fp, 0L, SEEK_END);
    len = ftell (fp);
    fseek (fp, 0L, SEEK_SET);
    buf = malloc (sizeof (char) * (len + 1));
    if (!buf)
    {
	ret = FcFalse;
	goto bail1;
    }
    fread (buf, (size_t)len, sizeof (char), fp);
    buf[len] = 0;

    ret = FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) buf, FcTrue);
bail1:
    fclose (fp);
    if (buf)
	free (buf);

    return ret;
}

int
main (int argc, char **argv)
{
    FcConfig *config;
    int retval = 0;

    if (argc < 3)
    {
	fprintf(stderr, "Usage: %s <conf file> <test scenario>\n", argv[0]);
	return 1;
    }

    config = FcConfigCreate ();
    if (!load_config (config, argv[1]))
    {
	fprintf(stderr, "E: Failed to load config\n");
	retval = 1;
	goto bail1;
    }
    if (!run_scenario (config, argv[2]))
    {
	retval = 1;
	goto bail1;
    }
bail1:
    FcConfigDestroy (config);

    return retval;
}
