-- deinflection rules (ordered by appearance in tae kim's japanese grammar guide)
create temporary table deinflection_temp (tag, kana_in, kana_out, rules_in, rules_out);
insert into deinflection_temp values
	-- negative <https://guidetojapanese.org/learn/grammar/negativeverbs>
	('infl:negative',   'ない', 'る', 'a', 'ru'),
	('infl:negative', 'わない', 'う', 'a', 'u'),
	('infl:negative', 'かない', 'く', 'a', 'u'),
	('infl:negative', 'がない', 'ぐ', 'a', 'u'),
	('infl:negative', 'さない', 'す', 'a', 'u'),
	('infl:negative', 'たない', 'つ', 'a', 'u'),
	('infl:negative', 'なない', 'ぬ', 'a', 'u'),
	('infl:negative', 'ばない', 'ぶ', 'a', 'u'),
	('infl:negative', 'まない', 'む', 'a', 'u'),
	('infl:negative', 'らない', 'る', 'a', 'u'),
	('infl:negative', 'しない', 'する', 'a', 's'),
	('infl:negative', 'こない', 'くる', 'a', 'k'),
	('infl:negative', '来ない', '来る', 'a', 'k'),
	-- ('infl:negative',   'ない', 'ある', 'a', 'ru'), -- this one may cause problems (?)
	-- ('infl:negative',   'ない', '', 'a', 'ru'), -- this one may cause problems (?)

	-- past tense <https://guidetojapanese.org/learn/grammar/past_tense>
	('infl:tense:past',   'た', 'る', 'a', 'ru'),
	('infl:tense:past', 'した', 'す', 'a', 'u'),
	('infl:tense:past', 'いた', 'く', 'a', 'u'),
	('infl:tense:past', 'いだ', 'ぐ', 'a', 'u'),
	('infl:tense:past', 'んだ', 'む', 'a', 'u'),
	('infl:tense:past', 'んだ', 'ぬ', 'a', 'u'),
	('infl:tense:past', 'んだ', 'ぶ', 'a', 'u'),
	('infl:tense:past', 'った', 'う', 'a', 'u'),
	('infl:tense:past', 'った', 'つ', 'a', 'u'),
	('infl:tense:past', 'った', 'る', 'a', 'u'),
	('infl:tense:past', 'した', 'する', 'a', 's'),
	('infl:tense:past', 'きた', 'くる', 'a', 'k'),
	('infl:tense:past', '来た', 'くる', 'a', 'k'),
	('infl:tense:past', '行った', '行く', 'a', ''),
	('infl:tense:past', 'かった', 'い', 'a', 'a'), -- past negative

	-- adjective to adverb <https://guidetojapanese.org/learn/grammar/adverbs>
	('infl:adverb', 'く', 'い', 'a', 'i'),
	-- TODO: na-adjectives aren't deconjugated

	-- polite form <https://guidetojapanese.org/learn/grammar/polite>
	('infl:polite:masu',   'ます', 'る', 'a', 'ru'),
	('infl:polite:masu', 'います', 'う', 'a', 'u'),
	('infl:polite:masu', 'きます', 'く', 'a', 'u'),
	('infl:polite:masu', 'ぎます', 'ぐ', 'a', 'u'),
	('infl:polite:masu', 'します', 'す', 'a', 'u'),
	('infl:polite:masu', 'ちます', 'つ', 'a', 'u'),
	('infl:polite:masu', 'にます', 'ぬ', 'a', 'u'),
	('infl:polite:masu', 'びます', 'ぶ', 'a', 'u'),
	('infl:polite:masu', 'みます', 'む', 'a', 'u'),
	('infl:polite:masu', 'ります', 'る', 'a', 'u'),
	('infl:polite:masu', 'します', 'する', 'a', 's'),
	('infl:polite:masu', 'きます', 'くる', 'a', 'k'),
	('infl:polite:masu', '来ます', '来る', 'a', 'k'),
	('infl:polite:masu infl:negative',   'ません', 'る', 'a', 'ru'),
	('infl:polite:masu infl:negative', 'いません', 'う', 'a', 'u'),
	('infl:polite:masu infl:negative', 'きません', 'く', 'a', 'u'),
	('infl:polite:masu infl:negative', 'ぎません', 'ぐ', 'a', 'u'),
	('infl:polite:masu infl:negative', 'しません', 'す', 'a', 'u'),
	('infl:polite:masu infl:negative', 'ちません', 'つ', 'a', 'u'),
	('infl:polite:masu infl:negative', 'にません', 'ぬ', 'a', 'u'),
	('infl:polite:masu infl:negative', 'びません', 'ぶ', 'a', 'u'),
	('infl:polite:masu infl:negative', 'みません', 'む', 'a', 'u'),
	('infl:polite:masu infl:negative', 'りません', 'る', 'a', 'u'),
	('infl:polite:masu infl:negative', 'しません', 'する', 'a', 's'),
	('infl:polite:masu infl:negative', 'きません', 'くる', 'a', 'k'),
	('infl:polite:masu infl:negative', '来ません', '来る', 'a', 'k'),
	('infl:polite:masu infl:tense:past',   'ました', 'る', 'a', 'ru'),
	('infl:polite:masu infl:tense:past', 'いました', 'う', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'きました', 'く', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'ぎました', 'ぐ', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'しました', 'す', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'ちました', 'つ', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'にました', 'ぬ', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'びました', 'ぶ', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'みました', 'む', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'りました', 'る', 'a', 'u'),
	('infl:polite:masu infl:tense:past', 'しました', 'する', 'a', 's'),
	('infl:polite:masu infl:tense:past', 'きました', 'くる', 'a', 'k'),
	('infl:polite:masu infl:tense:past', '来ました', '来る', 'a', 'k'),
	('infl:polite:masu infl:tense:past infl:negative',   'ませんでした', 'る', 'a', 'ru'),
	('infl:polite:masu infl:tense:past infl:negative', 'いませんでした', 'う', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'きませんでした', 'く', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'ぎませんでした', 'ぐ', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'しませんでした', 'す', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'ちませんでした', 'つ', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'にませんでした', 'ぬ', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'びませんでした', 'ぶ', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'みませんでした', 'む', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'りませんでした', 'る', 'a', 'u'),
	('infl:polite:masu infl:tense:past infl:negative', 'しませんでした', 'する', 'a', 's'),
	('infl:polite:masu infl:tense:past infl:negative', 'きませんでした', 'くる', 'a', 'k'),
	('infl:polite:masu infl:tense:past infl:negative', '来ませんでした', '来る', 'a', 'k'),
	-- ('infl:polite:masu infl:tense:past infl:negative', 'くありません', 'い', 'a', 'i'), -- reality check (should not be needed)

	-- TODO: compound nouns and adjectives <https://guidetojapanese.org/learn/grammar/compound>

	-- te-form <https://guidetojapanese.org/learn/grammar/compound>
	('infl:suffix:te',   'て',   'た', 'a', 'ru'),
	('infl:suffix:te', 'して', 'した', 'a', 's u'),
	('infl:suffix:te', 'いて', 'いた', 'a', 'u'),
	('infl:suffix:te', 'いで', 'いだ', 'a', 'u'),
	('infl:suffix:te', 'んで', 'んだ', 'a', 'u'),
	('infl:suffix:te', 'って', 'った', 'a', 'u'),
	('infl:suffix:te', 'きて', 'きた', 'a', 'k'),
	('infl:suffix:te', '来て', '来た', 'a', 'k'),
	('infl:suffix:te', 'くて', 'い', 'a', 'a'),
	('infl:suffix:te', 'よくて', 'いい', 'a', 'a'), -- exception

	-- -tari lists <https://guidetojapanese.org/learn/grammar/compound>
	('infl:suffix:tari',   'たり',   'た', 'a', 'ru'),
	('infl:suffix:tari', 'したり', 'した', 'a', 's u'),
	('infl:suffix:tari', 'いたり', 'いた', 'a', 'u'),
	('infl:suffix:tari', 'いだり', 'いだ', 'a', 'u'),
	('infl:suffix:tari', 'んだり', 'んだ', 'a', 'u'),
	('infl:suffix:tari', 'ったり', 'った', 'a', 'u'),
	('infl:suffix:tari', 'きたり', 'きた', 'a', 'k'),
	('infl:suffix:tari', '来たり', '来た', 'a', 'k'),

	-- -sa (adjective->noun) <https://guidetojapanese.org/learn/grammar/amount>
	('infl:suffix:sa class:noun', 'さ', '', 'a', 'na'),
	('infl:suffix:sa class:noun', 'さ', 'い', 'a', 'i'),

	-- continuous tense <https://guidetojapanese.org/learn/grammar/teform>
	('infl:tense:cont', 'いる', '', 'a', 'a'),

	-- potential form <https://guidetojapanese.org/learn/grammar/potential>
	('infl:potential', 'られる', 'る', 'a', 'ru'),
	('infl:potential', 'える', 'う', 'a', 'u'),
	('infl:potential', 'ける', 'く', 'a', 'u'),
	('infl:potential', 'げる', 'ぐ', 'a', 'u'),
	('infl:potential', 'せる', 'す', 'a', 'u'),
	('infl:potential', 'てる', 'つ', 'a', 'u'),
	('infl:potential', 'ねる', 'ぬ', 'a', 'u'),
	('infl:potential', 'べる', 'ぶ', 'a', 'u'),
	('infl:potential', 'める', 'む', 'a', 'u'),
	('infl:potential', 'れる', 'る', 'a', 'u'),
	('infl:potential', 'できる', 'する', 'a', 's'),
	('infl:potential', 'こられる', 'くる', 'a', 'k'),
	('infl:potential', 'ありうる', 'ある', 'a', ''), -- exception
	('infl:potential', 'ありえる', 'ある', 'a', ''), -- exception

	-- conditionals <https://guidetojapanese.org/learn/grammar/conditionals>
	('infl:suffix:ba', 'えば', 'う', 'a', 'u'),
	('infl:suffix:ba', 'けば', 'く', 'a', 'u'),
	('infl:suffix:ba', 'げば', 'ぐ', 'a', 'u'),
	('infl:suffix:ba', 'せば', 'す', 'a', 'u'),
	('infl:suffix:ba', 'てば', 'つ', 'a', 'u'),
	('infl:suffix:ba', 'ねば', 'ぬ', 'a', 'u'),
	('infl:suffix:ba', 'べば', 'ぶ', 'a', 'u'),
	('infl:suffix:ba', 'めば', 'む', 'a', 'u'),
	('infl:suffix:ba', 'れば', 'る', 'a', 'u ru'),
	('infl:suffix:ba', 'ければ', 'い', 'a', 'a'),
	-- TODO: 〜であれば (deconjugates to です i think?)

	-- auxiliary rules
	('class:verb:suru-included', 'する', '', 's', ''); -- deconjugate suru verbs into stem

-- rule/bitmask lookup table
create temporary table rule_map (tag, name, mask);
insert into rule_map values
	(null,                 'a',   -1    ), -- all      (allow all rules in)
	(null,                 '',    0     ), --          (nothing)
	('infl:reason:ru',     'ru',  1 << 0), -- 一段活用 (ichidan a.k.a. ru-verbs in tae kim's japanese grammar guide)
	('infl:reason:u',      'u',   1 << 1), -- 五段活用 (godan a.k.a. u-verbs in tae kim's japanese grammar guide)
	('infl:reason:suru',   's',   1 << 2), -- する     (suru)
	('infl:reason:kuru',   'k',   1 << 3), -- くる     (kuru)
	(null,                 'z',   1 << 4), -- ずる     (zuru)
	('infl:reason:adj:i',  'i',   1 << 5), -- 形容詞   (i-adjective)
	(null,                 'iru', 1 << 6), -- 〜いる   (temporary iru for progressive tense)
	('infl:reason:adj:na', 'na',  1 << 7); -- 形容動詞 (na-adjective)

-- add tags to db
insert into deinflection_rules (mask, tag)
select mask, tag
from rule_map
where tag is not null;

-- convert space-separated strings to bitmasks and insert into deinflection table
insert into deinflection (tag, kana_in, kana_out, rules_in, rules_out)
with temp_deinflection_map(tag, kana_in, kana_out, rules_in_stack, rules_in, rules_out_stack, rules_out) as (
	select
		tag,
		kana_in,
		kana_out,
		rules_in || ' ',
		'',
		rules_out || ' ',
		''
	from deinflection_temp
	union
	select
		tag,
		kana_in,
		kana_out,
		substr(rules_in_stack, instr(rules_in_stack, ' ') + 1),
		replace(substr(rules_in_stack, 0, instr(rules_in_stack, ' ')), ' ', ''),
		substr(rules_out_stack, instr(rules_out_stack, ' ') + 1),
		replace(substr(rules_out_stack, 0, instr(rules_out_stack, ' ')), ' ', '')
	from temp_deinflection_map
	where
		(length(rules_in_stack) > 1) or
		(length(rules_out_stack) > 1)
)
select
	temp_deinflection_map.tag,
	temp_deinflection_map.kana_in,
	temp_deinflection_map.kana_out,
	-- NOTE: sum() should really be bitwise and across all rows after group by
	-- here. be careful to not specify rules more than once in these columns, or
	-- any other rule if the column has 'a'.
	sum(rule_map_in.mask) as rules_in,
	sum(rule_map_out.mask) as rules_out
from temp_deinflection_map
join rule_map as rule_map_in on rule_map_in.name = temp_deinflection_map.rules_in
join rule_map as rule_map_out on rule_map_out.name = temp_deinflection_map.rules_out
group by
	temp_deinflection_map.tag,
	temp_deinflection_map.kana_in,
	temp_deinflection_map.kana_out;

