// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:generate go run gen.go gen_common.go

// Package number contains tools and data for formatting numbers.
package number

import (
	"unicode/utf8"

	"golang.org/x/text/internal/language/compact"
	"golang.org/x/text/language"
)

// Info holds number formatting configuration data.
type Info struct {
	system   systemData // numbering system information
	symIndex symOffset  // index to symbols
}

// InfoFromLangID returns a Info for the given compact language identifier and
// numbering system identifier. If system is the empty string, the default
// numbering system will be taken for that language.
func InfoFromLangID(compactIndex compact.ID, numberSystem string) Info {
	p := langToDefaults[compactIndex]
	// Lookup the entry for the language.
	pSymIndex := symOffset(0) // Default: Latin, default symbols
	system, ok := systemMap[numberSystem]
	if !ok {
		// Take the value for the default numbering system. This is by far the
		// most common case as an alternative numbering system is hardly used.
		if p&hasNonLatnMask == 0 { // Latn digits.
			pSymIndex = p
		} else { // Non-Latn or multiple numbering systems.
			// Take the first entry from the alternatives list.
			data := langToAlt[p&^hasNonLatnMask]
			pSymIndex = data.symIndex
			system = data.system
		}
	} else {
		langIndex := compactIndex
		ns := system
	outerLoop:
		for ; ; p = langToDefaults[langIndex] {
			if p&hasNonLatnMask == 0 {
				if ns == 0 {
					// The index directly points to the symbol data.
					pSymIndex = p
					break
				}
				// Move to the parent and retry.
				langIndex = langIndex.Parent()
			} else {
				// The index points to a list of symbol data indexes.
				for _, e := range langToAlt[p&^hasNonLatnMask:] {
					if e.compactTag != langIndex {
						if langIndex == 0 {
							// The CLDR root defines full symbol information for
							// all numbering systems (even though mostly by
							// means of aliases). Fall back to the default entry
							// for Latn if there is no data for the numbering
							// system of this language.
							if ns == 0 {
								break
							}
							// Fall back to Latin and start from the original
							// language. See
							// http://unicode.org/reports/tr35/#Locale_Inheritance.
							ns = numLatn
							langIndex = compactIndex
							continue outerLoop
						}
						// Fall back to parent.
						langIndex = langIndex.Parent()
					} else if e.system == ns {
						pSymIndex = e.symIndex
						break outerLoop
					}
				}
			}
		}
	}
	if int(system) >= len(numSysData) { // algorithmic
		// Will generate ASCII digits in case the user inadvertently calls
		// WriteDigit or Digit on it.
		d := numSysData[0]
		d.id = system
		return Info{
			system:   d,
			symIndex: pSymIndex,
		}
	}
	return Info{
		system:   numSysData[system],
		symIndex: pSymIndex,
	}
}

// InfoFromTag returns a Info for the given language tag.
func InfoFromTag(t language.Tag) Info {
	return InfoFromLangID(tagToID(t), t.TypeForKey("nu"))
}

// IsDecimal reports if the numbering system can convert decimal to native
// symbols one-to-one.
func (n Info) IsDecimal() bool {
	return int(n.system.id) < len(numSysData)
}

// WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII
// digit to dst and reports the number of bytes written. dst must be large
// enough to hold the rune (can be up to utf8.UTFMax bytes).
func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
	copy(dst, n.system.zero[:n.system.digitSize])
	dst[n.system.digitSize-1] += byte(asciiDigit - '0')
	return int(n.system.digitSize)
}

// AppendDigit appends the UTF-8 sequence for n corresponding to the given digit
// to dst and reports the number of bytes written. dst must be large enough to
// hold the rune (can be up to utf8.UTFMax bytes).
func (n Info) AppendDigit(dst []byte, digit byte) []byte {
	dst = append(dst, n.system.zero[:n.system.digitSize]...)
	dst[len(dst)-1] += digit
	return dst
}

// Digit returns the digit for the numbering system for the corresponding ASCII
// value. For example, ni.Digit('3') could return '三'. Note that the argument
// is the rune constant '3', which equals 51, not the integer constant 3.
func (n Info) Digit(asciiDigit rune) rune {
	var x [utf8.UTFMax]byte
	n.WriteDigit(x[:], asciiDigit)
	r, _ := utf8.DecodeRune(x[:])
	return r
}

// Symbol returns the string for the given symbol type.
func (n Info) Symbol(t SymbolType) string {
	return symData.Elem(int(symIndex[n.symIndex][t]))
}

func formatForLang(t language.Tag, index []byte) *Pattern {
	return &formats[index[tagToID(t)]]
}

func tagToID(t language.Tag) compact.ID {
	id, _ := compact.RegionalID(compact.Tag(t))
	return id
}
