// Copyright 2017-2022 The MathJax Consortium
// SPDX-License-Identifier: Apache-2.0
// Sources: ts/input/tex/ams/{AmsMethods,AmsItems}.ts, FlalignItem and XalignAt.

package tex

import (
	

	
)

// amsFlalignLayout retains the source distinction between authored entries,
// declared equation pairs, and the fit columns inserted by EndRow.
type amsFlalignLayout struct {
	name       string
	entries    float64
	padded     bool
	center     bool
	zeroLabel  bool
	maxColumns int
}

func newAMSFlalignLayout(,  string) *amsFlalignLayout {
	 := &amsFlalignLayout{name: , center: !isAMSXAlignAt(), zeroLabel: isAMSXAlignAt()}
	if isAMSXAlignAt() {
		.padded =  != "xxalignat"
		// The scanner has already validated decimal digits. Empty and zero
		// counts disable the constraint; other counts use JavaScript's numeric
		// representation rather than a machine-width integer conversion.
		if  != "" {
			,  := strconv.ParseFloat(, 64)
			.entries = 2 * 
		}
	}
	return 
}

func ( *amsFlalignLayout) ( int) error {
	if .entries != 0 && float64() > .entries {
		return texError("XalignOverflow", "Extra & in row of %s", .name)
	}
	return nil
}

func ( *amsFlalignLayout) ( *mml.Node) {
	 := append([]*mml.Node(nil), .Children...)
	for float64(len()) < .entries {
		 = append(, node("mtd"))
	}
	 := make([]*mml.Node, 0, len()+len()/2+2)
	if .padded {
		 = append(, node("mtd"))
	}
	for len() != 0 {
		 = append(, [0])
		 = [1:]
		if len() != 0 {
			 = append(, [0])
			 = [1:]
		}
		if len() != 0 || .padded {
			 = append(, node("mtd"))
		}
	}
	.SetChildren()
	if len() > .maxColumns {
		.maxColumns = len()
	}
}

func ( *amsFlalignLayout) ( *mml.Node) *mml.Node {
	if .zeroLabel {
		 := node("mpadded", .Children...)
		.Attributes.Set("width", 0)
		.Attributes.Set("lspace", "-1width")
		.SetChildren([]*mml.Node{forcedRow([]*mml.Node{}, true)})
	}
	return 
}

func ( *amsFlalignLayout) ( *mml.Node) {
	, ,  := "right left center", "auto auto fit", "0.8em"
	if .padded {
		,  = "center right left", "fit auto auto"
	}
	if .zeroLabel {
		 = "0"
	}
	resetTableAttributes(,
		"width", "100%",
		"displaystyle", true,
		"columnalign", repeatAMSEqnArrayDefinition(, .maxColumns),
		"columnspacing", "0em",
		"columnwidth", repeatAMSEqnArrayDefinition(, .maxColumns),
		"rowspacing", "3pt",
		"side", "right",
		"minlabelspacing", ,
		"data-width-includes-label", true,
	)
	if .center && .maxColumns <= 2 {
		.Attributes.Explicit().Delete("width")
	}
}

func ( *parser) ( string) ([]*mml.Node, error) {
	 := ""
	if isAMSXAlignAt() {
		var  error
		,  = .readEquationPairCount()
		if  != nil {
			return nil, 
		}
	}
	if  := .checkEquationEnvironment();  != nil {
		return nil, 
	}
	 := newAMSFlalignLayout(, )
	 := .amsTags()
	 :=  == "flalign" ||  == "xalignat"
	.start(, , )
	defer .end()
	,  := .captureEnvironment()
	if  != nil {
		return nil, 
	}
	 := node("mtable")
	var  []*mml.Node
	 := &arrayRowSpacing{}
	 = .parseArrayBody(, arrayBodyOwner{
		rules:      newArrayRules(),
		hasEntries: func() bool { return len() != 0 },
		endEntry: func( []*mml.Node,  *arrayCellState) error {
			if len() != 0 {
				 = fixInitialMO()
			}
			 = append(, node("mtd", matrixCellContent()))
			return .endEntry(len())
		},
		endRow: func() error {
			 := node("mtr", ...)
			.endRow()
			,  := .getTag()
			if  != nil {
				return 
			}
			if  != nil {
				 = node("mlabeledtr", append([]*mml.Node{.label()}, .Children...)...)
			}
			.clearTag()
			.AppendChild()
			 = nil
			.rows++
			return nil
		},
		addSpacing: .add,
	})
	if  != nil {
		return nil, 
	}
	.endTable()
	.apply(, "3pt")

	return []*mml.Node{finishArrayRules()}, nil
}