// 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/ioutil"
	"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(ioutil.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
}
