// Copyright 2015 The Vanadium 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 compile

import (
	"fmt"
	"regexp"
	"strconv"

	"v.io/v23/i18n"
	"v.io/v23/vdl"
	"v.io/x/ref/lib/vdl/parse"
)

// ErrorDef represents a user-defined error definition in the compiled results.
type ErrorDef struct {
	NamePos                     // name, parse position and docs
	Exported  bool              // is this error definition exported?
	ID        string            // error ID
	RetryCode vdl.WireRetryCode // retry action to be performed by client
	Params    []*Field          // list of positional parameter names and types
	Formats   []LangFmt         // list of language / format pairs
	English   string            // English format text from Formats
}

// LangFmt represents a language / format string pair.
type LangFmt struct {
	Lang i18n.LangID // IETF language tag
	Fmt  string      // i18n format string in the given language.
}

func (x *ErrorDef) String() string {
	return fmt.Sprintf("%+v", *x)
}

// compileErrorDefs fills in pkg with compiled error definitions.
func compileErrorDefs(pkg *Package, pfiles []*parse.File, env *Env) {
	for index := range pkg.Files {
		file, pfile := pkg.Files[index], pfiles[index]
		for _, ped := range pfile.ErrorDefs {
			name, detail := ped.Name, identDetail("error", file, ped.Pos)
			export, err := validIdent(name, reservedNormal)
			if err != nil {
				env.prefixErrorf(file, ped.Pos, err, "error %s invalid name", name)
				continue
			}
			if err := file.DeclareIdent(name, detail); err != nil {
				env.prefixErrorf(file, ped.Pos, err, "error %s name conflict", name)
				continue
			}
			id := pkg.Path + "." + name
			ed := &ErrorDef{NamePos: NamePos(ped.NamePos), Exported: export, ID: id}
			defineErrorActions(ed, name, ped.Actions, file, env)
			ed.Params = defineErrorParams(name, ped.Params, file, env)
			ed.Formats = defineErrorFormats(name, ped.Formats, ed.Params, file, env)
			// We require the "en" base language for at least one of the Formats, and
			// favor "en-US" if it exists.  This requirement is an attempt to ensure
			// there is at least one common language across all errors.
			for _, lf := range ed.Formats {
				if lf.Lang == i18n.LangID("en-US") {
					ed.English = lf.Fmt
					break
				}
				if ed.English == "" && i18n.BaseLangID(lf.Lang) == i18n.LangID("en") {
					ed.English = lf.Fmt
				}
			}
			if ed.English == "" {
				env.Errorf(file, ed.Pos, "error %s invalid (must define at least one English format)", name)
				continue
			}
			file.ErrorDefs = append(file.ErrorDefs, ed)
		}
	}
}

func defineErrorActions(ed *ErrorDef, name string, pactions []parse.StringPos, file *File, env *Env) {
	// We allow multiple actions to be specified in the parser, so that it's easy
	// to add new actions in the future.
	seenRetry := false
	for _, pact := range pactions {
		if retry, err := vdl.WireRetryCodeFromString(pact.String); err == nil {
			if seenRetry {
				env.Errorf(file, pact.Pos, "error %s action %s invalid (retry action specified multiple times)", name, pact.String)
				continue
			}
			seenRetry = true
			ed.RetryCode = retry
			continue
		}
		env.Errorf(file, pact.Pos, "error %s action %s invalid (unknown action)", name, pact.String)
	}
}

func defineErrorParams(name string, pparams []*parse.Field, file *File, env *Env) []*Field {
	var params []*Field
	seen := make(map[string]*parse.Field)
	for _, pparam := range pparams {
		pname, pos := pparam.Name, pparam.Pos
		if pname == "" {
			env.Errorf(file, pos, "error %s invalid (parameters must be named)", name)
			return nil
		}
		if dup := seen[pname]; dup != nil {
			env.Errorf(file, pos, "error %s param %s duplicate name (previous at %s)", name, pname, dup.Pos)
			continue
		}
		seen[pname] = pparam
		if _, err := validIdent(pname, reservedFirstRuneLower); err != nil {
			env.prefixErrorf(file, pos, err, "error %s param %s invalid", name, pname)
			continue
		}
		param := &Field{NamePos(pparam.NamePos), compileType(pparam.Type, file, env)}
		params = append(params, param)
	}
	return params
}

func defineErrorFormats(name string, plfs []parse.LangFmt, params []*Field, file *File, env *Env) []LangFmt {
	var lfs []LangFmt
	seen := make(map[i18n.LangID]parse.LangFmt)
	for _, plf := range plfs {
		pos, lang, fmt := plf.Pos(), i18n.LangID(plf.Lang.String), plf.Fmt.String
		if lang == "" {
			env.Errorf(file, pos, "error %s has empty language identifier", name)
			continue
		}
		if dup, ok := seen[lang]; ok {
			env.Errorf(file, pos, "error %s duplicate language %s (previous at %s)", name, lang, dup.Pos())
			continue
		}
		seen[lang] = plf
		xfmt, err := xlateErrorFormat(fmt, params)
		if err != nil {
			env.prefixErrorf(file, pos, err, "error %s language %s format invalid", name, lang)
			continue
		}
		lfs = append(lfs, LangFmt{lang, xfmt})
	}
	return lfs
}

// xlateErrorFormat translates the user-supplied format into the format
// expected by i18n, mainly translating parameter names into numeric indexes.
func xlateErrorFormat(format string, params []*Field) (string, error) {
	const prefix = "{1:}{2:}"
	if format == "" {
		return prefix, nil
	}
	// Create a map from param name to index.  The index numbering starts at 3,
	// since the first two params are the component and op name, and i18n formats
	// use 1-based indices.
	pmap := make(map[string]string)
	for ix, param := range params {
		pmap[param.Name] = strconv.Itoa(ix + 3)
	}
	tagRE, err := regexp.Compile(`\{\:?([0-9a-zA-Z_]+)\:?\}`)
	if err != nil {
		return "", err
	}
	result, pos := prefix+" ", 0
	for _, match := range tagRE.FindAllStringSubmatchIndex(format, -1) {
		// The tag submatch indices are available as match[2], match[3]
		if len(match) != 4 || match[2] < pos || match[2] > match[3] {
			return "", fmt.Errorf("internal error: bad regexp indices %v", match)
		}
		beg, end := match[2], match[3]
		tag := format[beg:end]
		if tag == "_" {
			continue // Skip underscore tags.
		}
		if _, err := strconv.Atoi(tag); err == nil {
			continue // Skip number tags.
		}
		xtag, ok := pmap[tag]
		if !ok {
			return "", fmt.Errorf("unknown param %q", tag)
		}
		// Replace tag with xtag in the result.
		result += format[pos:beg]
		result += xtag
		pos = end
	}
	if end := len(format); pos < end {
		result += format[pos:end]
	}
	return result, nil
}
