// Copyright (c) 2015-2021 Martin Hensel
// Copyright (c) 2026 luo-studio
// Copyright (c) 2026 erweixin (upstream RaTeX)
// SPDX-License-Identifier: Apache-2.0 AND MIT
//
// Go translation and modification of mhchemparser 4.1.1. Initial Go
// translation structure adapted from github.com/Luo-Studio/go-tex (MIT).

package mhchem

import (
	
	
)

// Output value: a polymorphic JSON-like list. Either a string (a TeX
// fragment) or a tagged map ({type_: "...", ...}).
type Value any

// goMachine drives a state machine over input. Mirrors upstream
// engine::go_machine.
func goMachine( *parserCtx, ,  string) ([]Value, error) {
	 = normalizeInput()
	if  == "" {
		return nil, nil
	}
	,  := .data.Machines[]
	if ! {
		return nil, errMsg("unknown state machine %s", )
	}
	 := "0"
	 := NewBuffer()
	var  []Value
	 := ""
	 := 10

	for {
		if  !=  {
			 = 10
			 = 
		} else {
			--
		}
		if  <= 0 {
			return nil, parserError("MhchemBugU", "mhchem bug U. Please report.")
		}

		 := .Transitions[]
		if  == nil {
			 = .Transitions["*"]
		}
		if  == nil {
			return nil, errMsg("no transitions for state %s", )
		}

		 := false
	:
		for ,  := range  {
			,  := matchPattern(.data, .Pattern, )
			if  != nil {
				return nil, 
			}
			if  == nil {
				continue
			}
			 = true
			 :=  == ""
			for ,  := range .Task.Action {
				,  := applyAction(, , , &.Token, &)
				if  != nil {
					return nil, 
				}
				 = append(, ...)
			}
			if .Task.NextState != nil {
				 = *.Task.NextState
			}
			if  {
				return , nil
			}
			if !.Task.Revisit {
				 = .Remainder
			}
			if !.Task.ToContinue {
				break 
			}
		}
		if ! {
			return nil, parserError("MhchemBugU", "mhchem bug U. Please report.")
		}
	}
}

func normalizeInput( string) string {
	var  strings.Builder
	.Grow(len())
	for ,  := range  {
		switch  {
		case '\n':
			.WriteByte(' ')
		case '−', '–', '—', '‐':
			.WriteByte('-')
		case '…':
			.WriteString("...")
		default:
			if  < 128 {
				.WriteByte(byte())
				continue
			}
			var  [4]byte
			 := utf8.EncodeRune([:], )
			.Write([:])
		}
	}
	return .String()
}

// parserCtx is the recursive driver context. Mirrors upstream ParserCtx.
type parserCtx struct {
	data *Data
}

func ( *parserCtx) (,  string) ([]Value, error) {
	return goMachine(, , )
}