// 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 plural

import (
	"fmt"
	"io"
	"reflect"
	"strconv"

	"golang.org/x/text/internal/catmsg"
	"golang.org/x/text/internal/number"
	"golang.org/x/text/language"
	"golang.org/x/text/message/catalog"
)

// TODO: consider deleting this interface. Maybe VisibleDigits is always
// sufficient and practical.

// Interface is used for types that can determine their own plural form.
type Interface interface {
	// PluralForm reports the plural form for the given language of the
	// underlying value. It also returns the integer value. If the integer value
	// is larger than fits in n, PluralForm may return a value modulo
	// 10,000,000.
	PluralForm(t language.Tag, scale int) (f Form, n int)
}

// Selectf returns the first case for which its selector is a match for the
// arg-th substitution argument to a formatting call, formatting it as indicated
// by format.
//
// The cases argument are pairs of selectors and messages. Selectors are of type
// string or Form. Messages are of type string or catalog.Message. A selector
// matches an argument if:
//   - it is "other" or Other
//   - it matches the plural form of the argument: "zero", "one", "two", "few",
//     or "many", or the equivalent Form
//   - it is of the form "=x" where x is an integer that matches the value of
//     the argument.
//   - it is of the form "<x" where x is an integer that is larger than the
//     argument.
//
// The format argument determines the formatting parameters for which to
// determine the plural form. This is especially relevant for non-integer
// values.
//
// The format string may be "", in which case a best-effort attempt is made to
// find a reasonable representation on which to base the plural form. Examples
// of format strings are:
//   - %.2f   decimal with scale 2
//   - %.2e   scientific notation with precision 3 (scale + 1)
//   - %d     integer
func Selectf(arg int, format string, cases ...interface{}) catalog.Message {
	var p parser
	// Intercept the formatting parameters of format by doing a dummy print.
	fmt.Fprintf(io.Discard, format, &p)
	m := &message{arg, kindDefault, 0, cases}
	switch p.verb {
	case 'g':
		m.kind = kindPrecision
		m.scale = p.scale
	case 'f':
		m.kind = kindScale
		m.scale = p.scale
	case 'e':
		m.kind = kindScientific
		m.scale = p.scale
	case 'd':
		m.kind = kindScale
		m.scale = 0
	default:
		// TODO: do we need to handle errors?
	}
	return m
}

type parser struct {
	verb  rune
	scale int
}

func (p *parser) Format(s fmt.State, verb rune) {
	p.verb = verb
	p.scale = -1
	if prec, ok := s.Precision(); ok {
		p.scale = prec
	}
}

type message struct {
	arg   int
	kind  int
	scale int
	cases []interface{}
}

const (
	// Start with non-ASCII to allow skipping values.
	kindDefault    = 0x80 + iota
	kindScale      // verb f, number of fraction digits follows
	kindScientific // verb e, number of fraction digits follows
	kindPrecision  // verb g, number of significant digits follows
)

var handle = catmsg.Register("golang.org/x/text/feature/plural:plural", execute)

func (m *message) Compile(e *catmsg.Encoder) error {
	e.EncodeMessageType(handle)

	e.EncodeUint(uint64(m.arg))

	e.EncodeUint(uint64(m.kind))
	if m.kind > kindDefault {
		e.EncodeUint(uint64(m.scale))
	}

	forms := validForms(cardinal, e.Language())

	for i := 0; i < len(m.cases); {
		if err := compileSelector(e, forms, m.cases[i]); err != nil {
			return err
		}
		if i++; i >= len(m.cases) {
			return fmt.Errorf("plural: no message defined for selector %v", m.cases[i-1])
		}
		var msg catalog.Message
		switch x := m.cases[i].(type) {
		case string:
			msg = catalog.String(x)
		case catalog.Message:
			msg = x
		default:
			return fmt.Errorf("plural: message of type %T; must be string or catalog.Message", x)
		}
		if err := e.EncodeMessage(msg); err != nil {
			return err
		}
		i++
	}
	return nil
}

func compileSelector(e *catmsg.Encoder, valid []Form, selector interface{}) error {
	form := Other
	switch x := selector.(type) {
	case string:
		if x == "" {
			return fmt.Errorf("plural: empty selector")
		}
		if c := x[0]; c == '=' || c == '<' {
			val, err := strconv.ParseUint(x[1:], 10, 16)
			if err != nil {
				return fmt.Errorf("plural: invalid number in selector %q: %v", selector, err)
			}
			e.EncodeUint(uint64(c))
			e.EncodeUint(val)
			return nil
		}
		var ok bool
		form, ok = countMap[x]
		if !ok {
			return fmt.Errorf("plural: invalid plural form %q", selector)
		}
	case Form:
		form = x
	default:
		return fmt.Errorf("plural: selector of type %T; want string or Form", selector)
	}

	ok := false
	for _, f := range valid {
		if f == form {
			ok = true
			break
		}
	}
	if !ok {
		return fmt.Errorf("plural: form %q not supported for language %q", selector, e.Language())
	}
	e.EncodeUint(uint64(form))
	return nil
}

func execute(d *catmsg.Decoder) bool {
	lang := d.Language()
	argN := int(d.DecodeUint())
	kind := int(d.DecodeUint())
	scale := -1 // default
	if kind > kindDefault {
		scale = int(d.DecodeUint())
	}
	form := Other
	n := -1
	if arg := d.Arg(argN); arg == nil {
		// Default to Other.
	} else if x, ok := arg.(number.VisibleDigits); ok {
		d := x.Digits(nil, lang, scale)
		form, n = cardinal.matchDisplayDigits(lang, &d)
	} else if x, ok := arg.(Interface); ok {
		// This covers lists and formatters from the number package.
		form, n = x.PluralForm(lang, scale)
	} else {
		var f number.Formatter
		switch kind {
		case kindScale:
			f.InitDecimal(lang)
			f.SetScale(scale)
		case kindScientific:
			f.InitScientific(lang)
			f.SetScale(scale)
		case kindPrecision:
			f.InitDecimal(lang)
			f.SetPrecision(scale)
		case kindDefault:
			// sensible default
			f.InitDecimal(lang)
			if k := reflect.TypeOf(arg).Kind(); reflect.Int <= k && k <= reflect.Uintptr {
				f.SetScale(0)
			} else {
				f.SetScale(2)
			}
		}
		var dec number.Decimal // TODO: buffer in Printer
		dec.Convert(f.RoundingContext, arg)
		v := number.FormatDigits(&dec, f.RoundingContext)
		if !v.NaN && !v.Inf {
			form, n = cardinal.matchDisplayDigits(d.Language(), &v)
		}
	}
	for !d.Done() {
		f := d.DecodeUint()
		if (f == '=' && n == int(d.DecodeUint())) ||
			(f == '<' && 0 <= n && n < int(d.DecodeUint())) ||
			form == Form(f) ||
			Other == Form(f) {
			return d.ExecuteMessage()
		}
		d.SkipMessage()
	}
	return false
}
