// Copyright 2017 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.

package number

import (
	"strconv"
	"unicode/utf8"

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

// TODO:
// - split out the logic that computes the visible digits from the rest of the
//   formatting code (needed for plural).
// - grouping of fractions

// Formatter contains all the information needed to render a number.
type Formatter struct {
	Pattern
	Info
	RoundingContext
}

func (f *Formatter) init(t language.Tag, index []uint8) {
	f.Info = InfoFromTag(t)
	for ; ; t = t.Parent() {
		if ci, ok := language.CompactIndex(t); ok {
			f.Pattern = formats[index[ci]]
			break
		}
	}
}

// InitPattern initializes a Formatter for the given Pattern.
func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
	f.Info = InfoFromTag(t)
	f.Pattern = *pat
}

// InitDecimal initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitDecimal(t language.Tag) {
	f.init(t, tagToDecimal)
}

// InitScientific initializes a Formatter using the default Pattern for the
// given language.
func (f *Formatter) InitScientific(t language.Tag) {
	f.init(t, tagToScientific)
}

// InitEngineering initializes a Formatter using the default Pattern for the
// given language.
func (f *Formatter) InitEngineering(t language.Tag) {
	f.init(t, tagToScientific)
	f.Pattern.MaxIntegerDigits = 3
	f.Pattern.MinIntegerDigits = 1
}

// InitPercent initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitPercent(t language.Tag) {
	f.init(t, tagToPercent)
}

// InitPerMille initializes a Formatter using the default Pattern for the given
// language.
func (f *Formatter) InitPerMille(t language.Tag) {
	f.init(t, tagToPercent)
	f.Pattern.DigitShift = 3
}

func (f *Formatter) Append(dst []byte, x interface{}) []byte {
	var d Decimal
	d.Convert(&f.RoundingContext, x)
	return f.Format(dst, &d)
}

func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
	var result []byte
	var postPrefix, preSuffix int
	if f.MinExponentDigits > 0 {
		result, postPrefix, preSuffix = appendScientific(dst, f, d)
	} else {
		result, postPrefix, preSuffix = appendDecimal(dst, f, d)
	}
	if f.PadRune == 0 {
		return result
	}
	width := int(f.FormatWidth)
	if count := utf8.RuneCount(result); count < width {
		insertPos := 0
		switch f.Flags & PadMask {
		case PadAfterPrefix:
			insertPos = postPrefix
		case PadBeforeSuffix:
			insertPos = preSuffix
		case PadAfterSuffix:
			insertPos = len(result)
		}
		num := width - count
		pad := [utf8.UTFMax]byte{' '}
		sz := 1
		if r := f.PadRune; r != 0 {
			sz = utf8.EncodeRune(pad[:], r)
		}
		extra := sz * num
		if n := len(result) + extra; n < cap(result) {
			result = result[:n]
			copy(result[insertPos+extra:], result[insertPos:])
		} else {
			buf := make([]byte, n)
			copy(buf, result[:insertPos])
			copy(buf[insertPos+extra:], result[insertPos:])
			result = buf
		}
		for ; num > 0; num-- {
			insertPos += copy(result[insertPos:], pad[:sz])
		}
	}
	return result
}

// appendDecimal appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
	if dst, ok := f.renderSpecial(dst, d); ok {
		return dst, 0, len(dst)
	}
	n := d.normalize()
	if maxSig := int(f.MaxSignificantDigits); maxSig > 0 {
		n.round(ToZero, maxSig)
	}
	digits := n.Digits
	exp := n.Exp
	exp += int32(f.Pattern.DigitShift)

	// Split in integer and fraction part.
	var intDigits, fracDigits []byte
	var numInt, numFrac int
	if exp > 0 {
		numInt = int(exp)
		if int(exp) >= len(digits) { // ddddd | ddddd00
			intDigits = digits
		} else { // ddd.dd
			intDigits = digits[:exp]
			fracDigits = digits[exp:]
			numFrac = len(fracDigits)
		}
	} else {
		fracDigits = digits
		numFrac = -int(exp) + len(digits)
	}
	// Cap integer digits. Remove *most-significant* digits.
	if f.MaxIntegerDigits > 0 && numInt > int(f.MaxIntegerDigits) {
		offset := numInt - int(f.MaxIntegerDigits)
		if offset > len(intDigits) {
			numInt = 0
			intDigits = nil
		} else {
			numInt = int(f.MaxIntegerDigits)
			intDigits = intDigits[offset:]
			// for keeping track of significant digits
			digits = digits[offset:]
		}
		// Strip leading zeros. Resulting number of digits is significant digits.
		for len(intDigits) > 0 && intDigits[0] == 0 {
			intDigits = intDigits[1:]
			digits = digits[1:]
			numInt--
		}
	}
	if f.MaxSignificantDigits == 0 && int(f.MaxFractionDigits) < numFrac {
		if extra := numFrac - int(f.MaxFractionDigits); extra > len(fracDigits) {
			numFrac = 0
			fracDigits = nil
		} else {
			numFrac = int(f.MaxFractionDigits)
			fracDigits = fracDigits[:len(fracDigits)-extra]
		}
	}

	neg := d.Neg && numInt+numFrac > 0
	affix, suffix := f.getAffixes(neg)
	dst = appendAffix(dst, f, affix, neg)
	savedLen := len(dst)

	minInt := int(f.MinIntegerDigits)
	if minInt == 0 && f.MinSignificantDigits > 0 {
		minInt = 1
	}
	// add leading zeros
	for i := minInt; i > numInt; i-- {
		dst = f.AppendDigit(dst, 0)
		if f.needsSep(i) {
			dst = append(dst, f.Symbol(SymGroup)...)
		}
	}
	i := 0
	for ; i < len(intDigits); i++ {
		dst = f.AppendDigit(dst, intDigits[i])
		if f.needsSep(numInt - i) {
			dst = append(dst, f.Symbol(SymGroup)...)
		}
	}
	for ; i < numInt; i++ {
		dst = f.AppendDigit(dst, 0)
		if f.needsSep(numInt - i) {
			dst = append(dst, f.Symbol(SymGroup)...)
		}
	}

	trailZero := int(f.MinFractionDigits) - numFrac
	if d := int(f.MinSignificantDigits) - len(digits); d > 0 && d > trailZero {
		trailZero = d
	}
	if numFrac > 0 || trailZero > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
		dst = append(dst, f.Symbol(SymDecimal)...)
	}
	// Add leading zeros
	for i := numFrac - len(fracDigits); i > 0; i-- {
		dst = f.AppendDigit(dst, 0)
	}
	i = 0
	for ; i < len(fracDigits); i++ {
		dst = f.AppendDigit(dst, fracDigits[i])
	}
	for ; trailZero > 0; trailZero-- {
		dst = f.AppendDigit(dst, 0)
	}
	// Ensure that at least one digit is written no matter what. This makes
	// things more robust, even though a pattern should always require at least
	// one fraction or integer digit.
	if len(dst) == savedLen {
		dst = f.AppendDigit(dst, 0)
	}
	return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}

// appendScientific appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendScientific(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
	if dst, ok := f.renderSpecial(dst, d); ok {
		return dst, 0, 0
	}
	// Significant digits are transformed by parser for scientific notation and
	// do not need to be handled here.
	maxInt, numInt := int(f.MaxIntegerDigits), int(f.MinIntegerDigits)
	if numInt == 0 {
		numInt = 1
	}
	maxSig := int(f.MaxFractionDigits) + numInt
	minSig := int(f.MinFractionDigits) + numInt
	n := d.normalize()
	if maxSig > 0 {
		n.round(ToZero, maxSig)
	}
	digits := n.Digits
	exp := n.Exp

	// If a maximum number of integers is specified, the minimum must be 1
	// and the exponent is grouped by this number (e.g. for engineering)
	if len(digits) == 0 {
		exp = 0
	} else if maxInt > numInt {
		// Correct the exponent to reflect a single integer digit.
		exp--
		numInt = 1
		// engineering
		// 0.01234 ([12345]e-1) -> 1.2345e-2  12.345e-3
		// 12345   ([12345]e+5) -> 1.2345e4  12.345e3
		d := int(exp) % maxInt
		if d < 0 {
			d += maxInt
		}
		exp -= int32(d)
		numInt += d
	} else {
		exp -= int32(numInt)
	}
	var intDigits, fracDigits []byte
	if numInt <= len(digits) {
		intDigits = digits[:numInt]
		fracDigits = digits[numInt:]
	} else {
		intDigits = digits
	}
	neg := d.Neg && len(digits) > 0
	affix, suffix := f.getAffixes(neg)
	dst = appendAffix(dst, f, affix, neg)
	savedLen := len(dst)

	i := 0
	for ; i < len(intDigits); i++ {
		dst = f.AppendDigit(dst, intDigits[i])
		if f.needsSep(numInt - i) {
			dst = append(dst, f.Symbol(SymGroup)...)
		}
	}
	for ; i < numInt; i++ {
		dst = f.AppendDigit(dst, 0)
		if f.needsSep(numInt - i) {
			dst = append(dst, f.Symbol(SymGroup)...)
		}
	}

	trailZero := minSig - numInt - len(fracDigits)
	if len(fracDigits) > 0 || trailZero > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
		dst = append(dst, f.Symbol(SymDecimal)...)
	}
	i = 0
	for ; i < len(fracDigits); i++ {
		dst = f.AppendDigit(dst, fracDigits[i])
	}
	for ; trailZero > 0; trailZero-- {
		dst = f.AppendDigit(dst, 0)
	}
	// Ensure that at least one digit is written no matter what. This makes
	// things more robust, even though a pattern should always require at least
	// one fraction or integer digit.
	if len(dst) == savedLen {
		dst = f.AppendDigit(dst, 0)
	}

	// exp
	dst = append(dst, f.Symbol(SymExponential)...)
	switch {
	case exp < 0:
		dst = append(dst, f.Symbol(SymMinusSign)...)
		exp = -exp
	case f.Flags&AlwaysExpSign != 0:
		dst = append(dst, f.Symbol(SymPlusSign)...)
	}
	buf := [12]byte{}
	b = strconv.AppendUint(buf[:0], uint64(exp), 10)
	for i := len(b); i < int(f.MinExponentDigits); i++ {
		dst = f.AppendDigit(dst, 0)
	}
	for _, c := range b {
		dst = f.AppendDigit(dst, c-'0')
	}
	return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}

func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
	str := f.Affix
	if str != "" {
		if f.NegOffset > 0 {
			if neg {
				str = str[f.NegOffset:]
			} else {
				str = str[:f.NegOffset]
			}
		}
		sufStart := 1 + str[0]
		affix = str[1:sufStart]
		suffix = str[sufStart+1:]
	} else if neg {
		affix = "-"
	}
	return affix, suffix
}

func (f *Formatter) renderSpecial(dst []byte, d *Decimal) (b []byte, ok bool) {
	if d.NaN {
		return fmtNaN(dst, f), true
	}
	if d.Inf {
		return fmtInfinite(dst, f, d), true
	}
	return dst, false
}

func fmtNaN(dst []byte, f *Formatter) []byte {
	return append(dst, f.Symbol(SymNan)...)
}

func fmtInfinite(dst []byte, f *Formatter, d *Decimal) []byte {
	if d.Neg {
		dst = append(dst, f.Symbol(SymMinusSign)...)
	}
	return append(dst, f.Symbol(SymInfinity)...)
}

func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte {
	quoting := false
	escaping := false
	for _, r := range affix {
		switch {
		case escaping:
			// escaping occurs both inside and outside of quotes
			dst = append(dst, string(r)...)
			escaping = false
		case r == '\\':
			escaping = true
		case r == '\'':
			quoting = !quoting
		case quoting:
			dst = append(dst, string(r)...)
		case r == '%':
			if f.DigitShift == 3 {
				dst = append(dst, f.Symbol(SymPerMille)...)
			} else {
				dst = append(dst, f.Symbol(SymPercentSign)...)
			}
		case r == '-' || r == '+':
			if neg {
				dst = append(dst, f.Symbol(SymMinusSign)...)
			} else {
				dst = append(dst, f.Symbol(SymPlusSign)...)
			}
		default:
			dst = append(dst, string(r)...)
		}
	}
	return dst
}
