import as Gr from "@iosevka/glyph/relation"

import [CreateEmptyTable] from "./table-util.mjs"

import [buildLigations] from "./gsub-ligation.mjs"
import [buildCCMP buildCCMPPostCvSs] from "./gsub-ccmp.mjs"
import [buildGrFeature] from "./gsub-gr.mjs"
import [buildFrac] from "./gsub-frac.mjs"
import [buildCVSS] from "./gsub-cv-ss.mjs"
import [buildLOCL] from "./gsub-locl.mjs"
import [buildGsubThousands] from "./gsub-thousands.mjs"
import [buildGsubTexture] from "./gsub-texture.mjs"
import [buildMarkMkmk] from "./gpos-mark-mkmk.mjs"

define GDEF_SIMPLE 1
define GDEF_LIGATURE 2
define GDEF_MARK 3

extern Set
extern Map

# GSUB
define [buildGSUB para glyphStore markGlyphs] : begin
	define gsub : CreateEmptyTable

	# NWID / WWID
	if para.enableNwidWwid : begin
		local grIgnore : if para.isQuasiProportional Gr.IsCompositeOrLigature null
		buildGrFeature gsub glyphStore Gr.Nwid grIgnore
		buildGrFeature gsub glyphStore Gr.Wwid grIgnore

	# lnum / onum
	buildGrFeature gsub glyphStore Gr.Lnum
	buildGrFeature gsub glyphStore Gr.Onum

	# Mosaic form
	buildGrFeature gsub glyphStore Gr.MosaicForm

	# zero is handled inside the CV/SS feature builder
	# As it is a cv/ss "cherry picking".

	# APLF
	buildGrFeature gsub glyphStore Gr.AplForm

	# numr / dnom
	buildGrFeature gsub glyphStore Gr.NumeratorForm
	buildGrFeature gsub glyphStore Gr.DenominatorForm

	# ccmp
	local ccmp : buildCCMP gsub glyphStore markGlyphs

	# Ligation
	if para.enableLigation : buildLigations gsub para para.ligationBuildups

	# frac
	buildFrac gsub glyphStore

	# THND
	buildGsubThousands gsub para glyphStore

	# cv##, ss##
	local cvs nothing
	set cvs : buildCVSS gsub para glyphStore

	# ccmp post cv/ss (for Ogonek shape transform)
	buildCCMPPostCvSs gsub ccmp glyphStore markGlyphs

	# locl
	# Builds last, but the lookups are added into the beginning of the lookup list
	buildLOCL gsub para glyphStore

	# TXTR, "texture" feature
	if (para.buildTextureFeature && !para.isQuasiProportional) : begin
		buildGsubTexture gsub glyphStore markGlyphs cvs

	gsub.finalize
	return gsub

# GPOS
define [buildGPOS para glyphStore markGlyphs] : begin
	define gpos : CreateEmptyTable
	buildMarkMkmk gpos glyphStore markGlyphs
	gpos.finalize
	return gpos

# GDEF
define [buildGDEF para glyphStore markGlyphs] : begin
	local GDEF { .glyphClassDef {.} .markAttachClassDef {.} .markGlyphSets {} }

	foreach { gn glyph } [glyphStore.namedEntries] : piecewise
		[markGlyphs.all.has gn] : set GDEF.glyphClassDef.(gn) GDEF_MARK
		[[regex '_'].test gn]   : set GDEF.glyphClassDef.(gn) GDEF_LIGATURE
		true                    : set GDEF.glyphClassDef.(gn) GDEF_SIMPLE

	local n 1
	local m : new Map
	foreach { gn clsStr } markGlyphs.markAttachClassDef : begin
		local clsNum : m.get clsStr
		if [not clsNum] : begin
			set clsNum n
			set n (n + 1)
			m.set clsStr clsNum

		set GDEF.markAttachClassDef.(gn) clsNum

	set GDEF.markGlyphSets markGlyphs.markGlyphSets

	return GDEF

export : define [buildOtl para glyphStore] : begin
	# Link glyph pairs by suffix
	Gr.linkSuffixPairGr glyphStore 'NWID' 'WWID' Gr.Nwid Gr.Wwid
	Gr.linkSuffixPairGr glyphStore 'lnum' 'onum' Gr.Lnum Gr.Onum
	Gr.linkSuffixGr     glyphStore 'aplForm'     Gr.AplForm

	local markGlyphs { .all [new Set] .markAttachClassDef [new Map] .markGlyphSets {} }
	local GPOS : buildGPOS para glyphStore markGlyphs
	local GDEF : buildGDEF para glyphStore markGlyphs
	local GSUB : buildGSUB para glyphStore markGlyphs

	# Make all diacritics join-l (Kitty #3716)
	foreach gnMark markGlyphs.all : begin
		Gr.Joining.or [glyphStore.queryByName gnMark] Gr.Joining.Classes.Left

	return [object GSUB GPOS GDEF]
