// 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 implements formatted I/O for localized strings with functions
// analogous to the fmt's print functions.
//
// NOTE: Under construction. See https://golang.org/design/text/12750-localization
// and its corresponding proposal issue https://golang.org/issues/12750.
package message // import "golang.org/x/text/message"

import (
	"fmt"
	"io"
	"strings"

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

// 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 {
	tag language.Tag

	cat *Catalog

	// 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.
}

// NewPrinter returns a Printer that formats messages tailored to language t.
func NewPrinter(t language.Tag) *Printer {
	return DefaultCatalog.Printer(t)
}

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

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

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

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

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

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

// Sprintf is like fmt.Sprintf, but using language-specific formatting.
func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
	msg, hasSub := p.lookup(key)
	if !hasSub {
		return fmt.Sprintf(msg) // work around limitation of fmt
	}
	return fmt.Sprintf(msg, p.bindArgs(a)...)
}

// 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) {
	msg, hasSub := p.lookup(key)
	if !hasSub {
		return fmt.Fprintf(w, msg) // work around limitation of fmt
	}
	return fmt.Fprintf(w, msg, p.bindArgs(a)...)
}

// Printf is like fmt.Printf, but using language-specific formatting.
func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
	msg, hasSub := p.lookup(key)
	if !hasSub {
		return fmt.Printf(msg) // work around limitation of fmt
	}
	return fmt.Printf(msg, p.bindArgs(a)...)
}

func (p *Printer) lookup(r Reference) (msg string, hasSub bool) {
	var id 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 s, ok := p.cat.get(p.tag, id); ok {
		msg = s
	}
	// fmt does not allow all arguments to be dropped in a format string. It
	// only allows arguments to be dropped if at least one of the substitutions
	// uses the positional marker (e.g. %[1]s). This hack works around this.
	// TODO: This is only an approximation of the parsing of substitution
	// patterns. Make more precise once we know if we can get by with fmt's
	// formatting, which may not be the case.
	for i := 0; i < len(msg)-1; i++ {
		if msg[i] == '%' {
			for i++; i < len(msg); i++ {
				if strings.IndexByte("[]#+- *01234567890.", msg[i]) < 0 {
					break
				}
			}
			if i < len(msg) && msg[i] != '%' {
				hasSub = true
				break
			}
		}
	}
	return msg, hasSub
}

// A Reference is a string or a message reference.
type Reference interface {
}

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

// bindArgs wraps arguments with implementation of fmt.Formatter, if needed.
func (p *Printer) bindArgs(a []interface{}) []interface{} {
	out := make([]interface{}, len(a))
	for i, x := range a {
		switch v := x.(type) {
		case fmt.Formatter:
			// Wrap the value with a Formatter that augments the State with
			// language-specific attributes.
			out[i] = &value{v, p}

			// NOTE: as we use fmt.Formatter, we can't distinguish between
			// regular and localized formatters, so we always need to wrap it.

			// TODO: handle
			// - numbers
			// - lists
			// - time?
		default:
			out[i] = x
		}
	}
	return out
}

// state implements "golang.org/x/text/internal/format".State.
type state struct {
	fmt.State
	p *Printer
}

func (s *state) Language() language.Tag { return s.p.tag }

var _ format.State = &state{}

type value struct {
	x fmt.Formatter
	p *Printer
}

func (v *value) Format(s fmt.State, verb rune) {
	v.x.Format(&state{s, v.p}, verb)
}
