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

import (
	"errors"
	"fmt"

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

// A Renderer renders a Message.
type Renderer interface {
	// Render renders the given string. The given string may be interpreted as a
	// format string, such as the one used by the fmt package or a template.
	Render(s string)

	// Arg returns the i-th argument passed to format a message. This method
	// should return nil if there is no such argument. Messages need access to
	// arguments to allow selecting a message based on linguistic features of
	// those arguments.
	Arg(i int) interface{}
}

// A Dictionary specifies a source of messages, including variables or macros.
type Dictionary interface {
	// Lookup returns the message for the given key. It returns false for ok if
	// such a message could not be found.
	Lookup(key string) (data string, ok bool)

	// TODO: consider returning an interface, instead of a string. This will
	// allow implementations to do their own message type decoding.
}

// An Encoder serializes a Message to a string.
type Encoder struct {
	// The root encoder is used for storing encoded variables.
	root *Encoder
	// The parent encoder provides the surrounding scopes for resolving variable
	// names.
	parent *Encoder

	tag language.Tag

	// buf holds the encoded message so far. After a message completes encoding,
	// the contents of buf, prefixed by the encoded length, are flushed to the
	// parent buffer.
	buf []byte

	// vars is the lookup table of variables in the current scope.
	vars []keyVal

	err    error
	inBody bool // if false next call must be EncodeMessageType
}

type keyVal struct {
	key    string
	offset int
}

// Language reports the language for which the encoded message will be stored
// in the Catalog.
func (e *Encoder) Language() language.Tag { return e.tag }

func (e *Encoder) setError(err error) {
	if e.root.err == nil {
		e.root.err = err
	}
}

// EncodeUint encodes x.
func (e *Encoder) EncodeUint(x uint64) {
	e.checkInBody()
	var buf [maxVarintBytes]byte
	n := encodeUint(buf[:], x)
	e.buf = append(e.buf, buf[:n]...)
}

// EncodeString encodes s.
func (e *Encoder) EncodeString(s string) {
	e.checkInBody()
	e.EncodeUint(uint64(len(s)))
	e.buf = append(e.buf, s...)
}

// EncodeMessageType marks the current message to be of type h.
//
// It must be the first call of a Message's Compile method.
func (e *Encoder) EncodeMessageType(h Handle) {
	if e.inBody {
		panic("catmsg: EncodeMessageType not the first method called")
	}
	e.inBody = true
	e.EncodeUint(uint64(h))
}

// EncodeMessage serializes the given message inline at the current position.
func (e *Encoder) EncodeMessage(m Message) error {
	e = &Encoder{root: e.root, parent: e, tag: e.tag}
	err := m.Compile(e)
	if _, ok := m.(*Var); !ok {
		e.flushTo(e.parent)
	}
	return err
}

func (e *Encoder) checkInBody() {
	if !e.inBody {
		panic("catmsg: expected prior call to EncodeMessageType")
	}
}

// stripPrefix indicates the number of prefix bytes that must be stripped to
// turn a single-element sequence into a message that is just this single member
// without its size prefix. If the message can be stripped, b[1:n] contains the
// size prefix.
func stripPrefix(b []byte) (n int) {
	if len(b) > 0 && Handle(b[0]) == msgFirst {
		x, n, _ := decodeUint(b[1:])
		if 1+n+int(x) == len(b) {
			return 1 + n
		}
	}
	return 0
}

func (e *Encoder) flushTo(dst *Encoder) {
	data := e.buf
	p := stripPrefix(data)
	if p > 0 {
		data = data[1:]
	} else {
		// Prefix the size.
		dst.EncodeUint(uint64(len(data)))
	}
	dst.buf = append(dst.buf, data...)
}

func (e *Encoder) addVar(key string, m Message) error {
	for _, v := range e.parent.vars {
		if v.key == key {
			err := fmt.Errorf("catmsg: duplicate variable %q", key)
			e.setError(err)
			return err
		}
	}
	scope := e.parent
	// If a variable message is Incomplete, and does not evaluate to a message
	// during execution, we fall back to the variable name. We encode this by
	// appending the variable name if the message reports it's incomplete.

	err := m.Compile(e)
	if err != ErrIncomplete {
		e.setError(err)
	}
	switch {
	case len(e.buf) == 1 && Handle(e.buf[0]) == msgFirst: // empty sequence
		e.buf = e.buf[:0]
		e.inBody = false
		fallthrough
	case len(e.buf) == 0:
		// Empty message.
		if err := String(key).Compile(e); err != nil {
			e.setError(err)
		}
	case err == ErrIncomplete:
		if Handle(e.buf[0]) != msgFirst {
			seq := &Encoder{root: e.root, parent: e}
			seq.EncodeMessageType(msgFirst)
			e.flushTo(seq)
			e = seq
		}
		// e contains a sequence; append the fallback string.
		e.EncodeMessage(String(key))
	}

	// Flush result to variable heap.
	offset := len(e.root.buf)
	e.flushTo(e.root)
	e.buf = e.buf[:0]

	// Record variable offset in current scope.
	scope.vars = append(scope.vars, keyVal{key: key, offset: offset})
	return err
}

const (
	substituteVar = iota
	substituteMacro
	substituteError
)

// EncodeSubstitution inserts a resolved reference to a variable or macro.
//
// This call must be matched with a call to ExecuteSubstitution at decoding
// time.
func (e *Encoder) EncodeSubstitution(name string, arguments ...int) {
	if arity := len(arguments); arity > 0 {
		// TODO: also resolve macros.
		e.EncodeUint(substituteMacro)
		e.EncodeString(name)
		for _, a := range arguments {
			e.EncodeUint(uint64(a))
		}
		return
	}
	for scope := e; scope != nil; scope = scope.parent {
		for _, v := range scope.vars {
			if v.key != name {
				continue
			}
			e.EncodeUint(substituteVar) // TODO: support arity > 0
			e.EncodeUint(uint64(v.offset))
			return
		}
	}
	// TODO: refer to dictionary-wide scoped variables.
	e.EncodeUint(substituteError)
	e.EncodeString(name)
	e.setError(fmt.Errorf("catmsg: unknown var %q", name))
}

// A Decoder deserializes and evaluates messages that are encoded by an encoder.
type Decoder struct {
	tag    language.Tag
	dst    Renderer
	macros Dictionary

	err  error
	vars string
	data string

	macroArg int // TODO: allow more than one argument
}

// NewDecoder returns a new Decoder.
//
// Decoders are designed to be reused for multiple invocations of Execute.
// Only one goroutine may call Execute concurrently.
func NewDecoder(tag language.Tag, r Renderer, macros Dictionary) *Decoder {
	return &Decoder{
		tag:    tag,
		dst:    r,
		macros: macros,
	}
}

func (d *Decoder) setError(err error) {
	if d.err == nil {
		d.err = err
	}
}

// Language returns the language in which the message is being rendered.
//
// The destination language may be a child language of the language used for
// encoding. For instance, a decoding language of "pt-PT"" is consistent with an
// encoding language of "pt".
func (d *Decoder) Language() language.Tag { return d.tag }

// Done reports whether there are more bytes to process in this message.
func (d *Decoder) Done() bool { return len(d.data) == 0 }

// Render implements Renderer.
func (d *Decoder) Render(s string) { d.dst.Render(s) }

// Arg implements Renderer.
//
// During evaluation of macros, the argument positions may be mapped to
// arguments that differ from the original call.
func (d *Decoder) Arg(i int) interface{} {
	if d.macroArg != 0 {
		if i != 1 {
			panic("catmsg: only macros with single argument supported")
		}
		i = d.macroArg
	}
	return d.dst.Arg(i)
}

// DecodeUint decodes a number that was encoded with EncodeUint and advances the
// position.
func (d *Decoder) DecodeUint() uint64 {
	x, n, err := decodeUintString(d.data)
	d.data = d.data[n:]
	if err != nil {
		d.setError(err)
	}
	return x
}

// DecodeString decodes a string that was encoded with EncodeString and advances
// the position.
func (d *Decoder) DecodeString() string {
	size := d.DecodeUint()
	s := d.data[:size]
	d.data = d.data[size:]
	return s
}

// SkipMessage skips the message at the current location and advances the
// position.
func (d *Decoder) SkipMessage() {
	n := int(d.DecodeUint())
	d.data = d.data[n:]
}

// Execute decodes and evaluates msg.
//
// Only one goroutine may call execute.
func (d *Decoder) Execute(msg string) error {
	d.err = nil
	if !d.execute(msg) {
		return ErrNoMatch
	}
	return d.err
}

func (d *Decoder) execute(msg string) bool {
	saved := d.data
	d.data = msg
	ok := d.executeMessage()
	d.data = saved
	return ok
}

// executeMessageFromData is like execute, but also decodes a leading message
// size and clips the given string accordingly.
//
// It reports the number of bytes consumed and whether a message was selected.
func (d *Decoder) executeMessageFromData(s string) (n int, ok bool) {
	saved := d.data
	d.data = s
	size := int(d.DecodeUint())
	n = len(s) - len(d.data)
	// Sanitize the setting. This allows skipping a size argument for
	// RawString and method Done.
	d.data = d.data[:size]
	ok = d.executeMessage()
	n += size - len(d.data)
	d.data = saved
	return n, ok
}

var errUnknownHandler = errors.New("catmsg: string contains unsupported handler")

// executeMessage reads the handle id, initializes the decoder and executes the
// message. It is assumed that all of d.data[d.p:] is the single message.
func (d *Decoder) executeMessage() bool {
	if d.Done() {
		// We interpret no data as a valid empty message.
		return true
	}
	handle := d.DecodeUint()

	var fn Handler
	mutex.Lock()
	if int(handle) < len(handlers) {
		fn = handlers[handle]
	}
	mutex.Unlock()
	if fn == nil {
		d.setError(errUnknownHandler)
		d.execute(fmt.Sprintf("\x02$!(UNKNOWNMSGHANDLER=%#x)", handle))
		return true
	}
	return fn(d)
}

// ExecuteMessage decodes and executes the message at the current position.
func (d *Decoder) ExecuteMessage() bool {
	n, ok := d.executeMessageFromData(d.data)
	d.data = d.data[n:]
	return ok
}

// ExecuteSubstitution executes the message corresponding to the substitution
// as encoded by EncodeSubstitution.
func (d *Decoder) ExecuteSubstitution() {
	switch x := d.DecodeUint(); x {
	case substituteVar:
		offset := d.DecodeUint()
		d.executeMessageFromData(d.vars[offset:])
	case substituteMacro:
		name := d.DecodeString()
		data, ok := d.macros.Lookup(name)
		old := d.macroArg
		// TODO: support macros of arity other than 1.
		d.macroArg = int(d.DecodeUint())
		switch {
		case !ok:
			// TODO: detect this at creation time.
			d.setError(fmt.Errorf("catmsg: undefined macro %q", name))
			fallthrough
		case !d.execute(data):
			d.dst.Render(name) // fall back to macro name.
		}
		d.macroArg = old
	case substituteError:
		d.dst.Render(d.DecodeString())
	default:
		panic("catmsg: unreachable")
	}
}
