// Copyright 2015 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 message // import "golang.org/x/text/message"

import (
	"io"
	"os"

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

// TODO: allow more than one goroutine per printer. This will allow porting from
// fmt much less error prone.

// A Printer implements language-specific formatted I/O analogous to the fmt
// package. Only one goroutine may use a Printer at the same time.
type Printer struct {
	// Wrap the fields in a hidden type to hide some of the implemented methods.
	printer printer

	// NOTE: limiting one goroutine per Printer allows for many optimizations
	// and simplifications. We can consider removing this restriction down the
	// road if it the benefits do not seem to outweigh the disadvantages.
}

type options struct {
	cat *catalog.Catalog
	// TODO:
	// - allow %s to print integers in written form (tables are likely too large
	//   to enable this by default).
	// - list behavior
	//
}

// An Option defines an option of a Printer.
type Option func(o *options)

// Catalog defines the catalog to be used.
func Catalog(c *catalog.Catalog) Option {
	return func(o *options) { o.cat = c }
}

// NewPrinter returns a Printer that formats messages tailored to language t.
func NewPrinter(t language.Tag, opts ...Option) *Printer {
	options := &options{
		cat: defaultCatalog,
	}
	for _, o := range opts {
		o(options)
	}
	p := &Printer{printer{
		tag: t,
	}}
	p.printer.toDecimal.InitDecimal(t)
	p.printer.toScientific.InitScientific(t)
	p.printer.catContext = options.cat.Context(t, &p.printer)
	return p
}

// Sprint is like fmt.Sprint, but using language-specific formatting.
func (p *Printer) Sprint(a ...interface{}) string {
	p.printer.reset()
	p.printer.doPrint(a)
	return p.printer.String()
}

// Fprint is like fmt.Fprint, but using language-specific formatting.
func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
	p.printer.reset()
	p.printer.doPrint(a)
	n64, err := io.Copy(w, &p.printer.Buffer)
	return int(n64), err
}

// Print is like fmt.Print, but using language-specific formatting.
func (p *Printer) Print(a ...interface{}) (n int, err error) {
	return p.Fprint(os.Stdout, a...)
}

// Sprintln is like fmt.Sprintln, but using language-specific formatting.
func (p *Printer) Sprintln(a ...interface{}) string {
	p.printer.reset()
	p.printer.doPrintln(a)
	return p.printer.String()
}

// Fprintln is like fmt.Fprintln, but using language-specific formatting.
func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
	p.printer.reset()
	p.printer.doPrintln(a)
	n64, err := io.Copy(w, &p.printer.Buffer)
	return int(n64), err
}

// Println is like fmt.Println, but using language-specific formatting.
func (p *Printer) Println(a ...interface{}) (n int, err error) {
	return p.Fprintln(os.Stdout, a...)
}

// Sprintf is like fmt.Sprintf, but using language-specific formatting.
func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
	lookupAndFormat(p, key, a)
	return p.printer.String()
}

// Fprintf is like fmt.Fprintf, but using language-specific formatting.
func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
	lookupAndFormat(p, key, a)
	return w.Write(p.printer.Bytes())
}

// Printf is like fmt.Printf, but using language-specific formatting.
func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
	lookupAndFormat(p, key, a)
	return os.Stdout.Write(p.printer.Bytes())
}

func lookupAndFormat(p *Printer, r Reference, a []interface{}) {
	p.printer.reset()
	p.printer.args = a
	var id, msg string
	switch v := r.(type) {
	case string:
		id, msg = v, v
	case key:
		id, msg = v.id, v.fallback
	default:
		panic("key argument is not a Reference")
	}

	if p.printer.catContext.Execute(id) == catalog.ErrNotFound {
		if p.printer.catContext.Execute(msg) == catalog.ErrNotFound {
			p.printer.Render(msg)
			return
		}
	}
}

// Arg implements catmsg.Renderer.
func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
	i--
	if uint(i) < uint(len(p.args)) {
		return p.args[i]
	}
	return nil
}

// Render implements catmsg.Renderer.
func (p *printer) Render(msg string) {
	p.doPrintf(msg)
}

// A Reference is a string or a message reference.
type Reference interface {
	// TODO: also allow []string
}

// Key creates a message Reference for a message where the given id is used for
// message lookup and the fallback is returned when no matches are found.
func Key(id string, fallback string) Reference {
	return key{id, fallback}
}

type key struct {
	id, fallback string
}
