/** @license 2022 Neil Edelman, distributed under the terms of the
 [MIT License](https://opensource.org/licenses/MIT).

 Scan journal entries for kjv references. */

#include "../src/journal.h"
#include "../src/kjv.h"
#include "../src/helper.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>

/*!conditions:re2c*/

static int scan(union date32 date, const char *const buffer,
	struct kjv *const kj) {
	const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1;
	enum kjv_book book = Revelation;
	uint32_t chapter, verse;
	enum YYCONDTYPE condition = yycline;
	size_t line = 1;
	char datestr[12] = {0};
	assert(buffer && kj);
	YYCURSOR = YYMARKER = yyt1 = buffer;
	/*!re2c /**/
	re2c:define:YYCTYPE = char;
	re2c:yyfill:enable = 0;
	re2c:define:YYGETCONDITION = "condition";
	re2c:define:YYSETCONDITION = "condition = @@;";
	re2c:define:YYGETCONDITION:naked = 1;
	re2c:define:YYSETCONDITION:naked = 1;

	unix_control = [\x01-\x08\x0a-\x1f\x7f];
	ws = [ \t];
	glyph = [^] \ ("\x00" | "\n" | unix_control | ws);
	natural = [1-9][0-9]*;
	lookat = ws* natural ":" natural [ab]?
		("-" (natural ":")? natural [ab]?)? ws* "--";
	*/
	for( ; ; ) { /*!re2c /**/
		<skip, book> * { goto catch; }
		<line> "\x00" { return 1; }
		<line> "\n" { line++; continue; }
		<line> * :=> skip
		<line> "Genesis" / lookat => book { book = Genesis; continue; }
		<line> "Exodus" / lookat => book { book = Exodus; continue; }
		/*| "Leviticus" | "Numbers" | "Deuteronomy"
		| "Joshua" | "Judges" | "Ruth" | "I"{1,2} " Samuel" | "I"{1,2} " Kings"
		| "I"{1,2} " Chronicles" | "Ezra" | "Nehemiah" | "Esther" | "Job"
		| "Psalms" | "Proverbs" | "Ecclesiastes" | "Song of Solomon" | "Isaiah"
		| "Jeremiah" | "Lamentations" | "Ezekiel" | "Daniel" | "Hosea" | "Joel"
		| "Amos" | "Obadiah" | "Jonah" | "Micah" | "Nahum" | "Habakkuk"
		| "Zephaniah" | "Haggai" | "Zechariah" | "Malachi" | "Matthew" | "Mark"
		| "Luke" | "John" | "Acts" | */
		<line> "Romans" / lookat => book { book = Romans; continue; }
		/*| "I"{1,2} " Corinthians"
		| "Galatians" | "Ephesians" | "Philippians" | "Colossians"
		| "I"{1,2} " Thessalonians" | "I"{1,2} " Timothy" | "Titus" | "Philemon"
		| "Hebrews" | "James" | "I"{1,2} " Peter" | "I"{1,3} " John" | "Jude"
		| "Revelation") @s1 ws* / bible_ref ws+ "--" ws+ "``" */
		//<line> [^\n\x00]* newline { printf("throw\n"); line++; continue; }
		<book> ws+ @s0 natural @s1 ":" @t0 natural @t1 [ab]? => skip {
			if(!helper_natural(s0, s1, &chapter)
				|| !helper_natural(t0, t1, &verse)) goto catch;
			union kjvcite cite
				= { .book = book, .chapter = chapter, .verse = verse };
			const size_t old_set_words = kj->set_words;
			char citestr[12];
			if(!kjv_add(kj, cite)) goto catch;
			if(!*datestr) date32_to_string(date, &datestr);
			kjvcite_to_string(cite, &citestr);
			printf("%s\t%zu\t%zu\t# %s\n",
				datestr, old_set_words, kj->set_words, citestr);
			continue;
		}
		<skip> [^\n\x00]* "\n" => line { line++; continue; }
		//=> bible { x->s0 = s0, x->s1 = s1; return x->symbol = KJV_BOOK, 1; }
	*/ }
catch:
	if(!errno) errno = EILSEQ;
	{
		char a[12];
		date32_to_string(date, &a);
		fprintf(stderr, "%s line %zu: unexpected.\n", a, line);
	}
	return 0;
}

int main(void) {
	int success = EXIT_SUCCESS;
	struct journal j;
	struct journal_iterator it;
	struct kjv kj = kjv();
	union date32 k;
	union load *v;
	size_t i;
	/*scan((union date32){.year=2000, .month=1, .day=1}, "\n\n\n"
		 "Romans 3:23 -- ``For all have sinned, "
		 "and come short of the glory of God.''\n", &kj);*/
	j = journal();
	if(!journal_is_valid(&j)) goto catch;
	fprintf(stderr, "Journal: %s.\n", journal_to_string(&j));
	printf("# date\told\tnew / %zu\n", kj.total_words);
	it = journal_begin(&j), i = 0; while(journal_next(&it, &k, &v)) {
		if(!scan(k, v->text, &kj)) goto catch;
		if(++i > 32) break;
	}
	goto finally;
catch:
	success = EXIT_FAILURE;
	perror("journal");
finally:
	journal_(&j);
	return success;
}
