package ftoa

import (
	
	

	
)

type FToStrMode int

const (
	// Either fixed or exponential format; round-trip
	ModeStandard FToStrMode = iota
	// Always exponential format; round-trip
	ModeStandardExponential
	// Round to <precision> digits after the decimal point; exponential if number is large
	ModeFixed
	// Always exponential format; <precision> significant digits
	ModeExponential
	// Either fixed or exponential format; <precision> significant digits
	ModePrecision
)

func insert( []byte,  int,  byte) []byte {
	 = append(, 0)
	copy([+1:], [:])
	[] = 
	return 
}

func expand( []byte,  int) []byte {
	 := len() + 
	if  <= cap() {
		return [:]
	}
	 := make([]byte, )
	copy(, )
	return 
}

func ( float64,  FToStrMode,  int,  []byte) []byte {
	if math.IsNaN() {
		 = append(, "NaN"...)
		return 
	}
	if math.IsInf(, 0) {
		if math.Signbit() {
			 = append(, '-')
		}
		 = append(, "Infinity"...)
		return 
	}

	if  == ModeFixed && ( >= 1e21 ||  <= -1e21) {
		 = ModeStandard
	}

	var  int
	var  bool
	 := len()

	if  != 0 { // also matches -0
		if  < 0 {
			 = append(, '-')
			 = -
			++
		}
		switch  {
		case ModeStandard, ModeStandardExponential:
			, ,  = fast.Dtoa(, fast.ModeShortest, 0, )
		case ModeExponential, ModePrecision:
			, ,  = fast.Dtoa(, fast.ModePrecision, , )
		}
	} else {
		 = append(, '0')
		,  = 1, true
	}
	if ! {
		,  = ftoa(, dtoaModes[],  >= ModeFixed, , )
	}
	 := false
	 := 0 /* Minimum number of significand digits required by mode and precision */
	 := len() - 

	switch  {
	case ModeStandard:
		if  < -5 ||  > 21 {
			 = true
		} else {
			 = 
		}
	case ModeFixed:
		if  >= 0 {
			 =  + 
		} else {
			 = 
		}
	case ModeExponential:
		//                    JS_ASSERT(precision > 0);
		 = 
		fallthrough
	case ModeStandardExponential:
		 = true
	case ModePrecision:
		//                    JS_ASSERT(precision > 0);
		 = 
		if  < -5 ||  >  {
			 = true
		}
	}

	for  <  {
		 = append(, '0')
		++
	}

	if  {
		/* Insert a decimal point if more than one significand digit */
		if  != 1 {
			 = insert(, +1, '.')
		}
		 = append(, 'e')
		if -1 >= 0 {
			 = append(, '+')
		}
		 = strconv.AppendInt(, int64(-1), 10)
	} else if  !=  {
		/* Some kind of a fraction in fixed notation */
		//                JS_ASSERT(decPt <= nDigits);
		if  > 0 {
			/* dd...dd . dd...dd */
			 = insert(, +, '.')
		} else {
			/* 0 . 00...00dd...dd */
			 = expand(, 2-)
			copy([+2-:], [:])
			[] = '0'
			[+1] = '.'
			for  :=  + 2;  < +2-; ++ {
				[] = '0'
			}
		}
	}

	return 
}