// Copyright 2013 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 cldr

// This file implements the various inheritance constructs defined by LDML.
// See https://www.unicode.org/reports/tr35/#Inheritance_and_Validity
// for more details.

import (
	"fmt"
	"log"
	"reflect"
	"regexp"
	"sort"
	"strings"
)

// fieldIter iterates over fields in a struct. It includes
// fields of embedded structs.
type fieldIter struct {
	v        reflect.Value
	index, n []int
}

func iter(v reflect.Value) fieldIter {
	if v.Kind() != reflect.Struct {
		log.Panicf("value %v must be a struct", v)
	}
	i := fieldIter{
		v:     v,
		index: []int{0},
		n:     []int{v.NumField()},
	}
	i.descent()
	return i
}

func (i *fieldIter) descent() {
	for f := i.field(); f.Anonymous && f.Type.NumField() > 0; f = i.field() {
		i.index = append(i.index, 0)
		i.n = append(i.n, f.Type.NumField())
	}
}

func (i *fieldIter) done() bool {
	return len(i.index) == 1 && i.index[0] >= i.n[0]
}

func skip(f reflect.StructField) bool {
	return !f.Anonymous && (f.Name[0] < 'A' || f.Name[0] > 'Z')
}

func (i *fieldIter) next() {
	for {
		k := len(i.index) - 1
		i.index[k]++
		if i.index[k] < i.n[k] {
			if !skip(i.field()) {
				break
			}
		} else {
			if k == 0 {
				return
			}
			i.index = i.index[:k]
			i.n = i.n[:k]
		}
	}
	i.descent()
}

func (i *fieldIter) value() reflect.Value {
	return i.v.FieldByIndex(i.index)
}

func (i *fieldIter) field() reflect.StructField {
	return i.v.Type().FieldByIndex(i.index)
}

type visitor func(v reflect.Value) error

var stopDescent = fmt.Errorf("do not recurse")

func (f visitor) visit(x interface{}) error {
	return f.visitRec(reflect.ValueOf(x))
}

// visit recursively calls f on all nodes in v.
func (f visitor) visitRec(v reflect.Value) error {
	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return nil
		}
		return f.visitRec(v.Elem())
	}
	if err := f(v); err != nil {
		if err == stopDescent {
			return nil
		}
		return err
	}
	switch v.Kind() {
	case reflect.Struct:
		for i := iter(v); !i.done(); i.next() {
			if err := f.visitRec(i.value()); err != nil {
				return err
			}
		}
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			if err := f.visitRec(v.Index(i)); err != nil {
				return err
			}
		}
	}
	return nil
}

// getPath is used for error reporting purposes only.
func getPath(e Elem) string {
	if e == nil {
		return "<nil>"
	}
	if e.enclosing() == nil {
		return e.GetCommon().name
	}
	if e.GetCommon().Type == "" {
		return fmt.Sprintf("%s.%s", getPath(e.enclosing()), e.GetCommon().name)
	}
	return fmt.Sprintf("%s.%s[type=%s]", getPath(e.enclosing()), e.GetCommon().name, e.GetCommon().Type)
}

// xmlName returns the xml name of the element or attribute
func xmlName(f reflect.StructField) (name string, attr bool) {
	tags := strings.Split(f.Tag.Get("xml"), ",")
	for _, s := range tags {
		attr = attr || s == "attr"
	}
	return tags[0], attr
}

func findField(v reflect.Value, key string) (reflect.Value, error) {
	v = reflect.Indirect(v)
	for i := iter(v); !i.done(); i.next() {
		if n, _ := xmlName(i.field()); n == key {
			return i.value(), nil
		}
	}
	return reflect.Value{}, fmt.Errorf("cldr: no field %q in element %#v", key, v.Interface())
}

var xpathPart = regexp.MustCompile(`(\pL+)(?:\[@(\pL+)='([\w-]+)'\])?`)

func walkXPath(e Elem, path string) (res Elem, err error) {
	for _, c := range strings.Split(path, "/") {
		if c == ".." {
			if e = e.enclosing(); e == nil {
				panic("path ..")
				return nil, fmt.Errorf(`cldr: ".." moves past root in path %q`, path)
			}
			continue
		} else if c == "" {
			continue
		}
		m := xpathPart.FindStringSubmatch(c)
		if len(m) == 0 || len(m[0]) != len(c) {
			return nil, fmt.Errorf("cldr: syntax error in path component %q", c)
		}
		v, err := findField(reflect.ValueOf(e), m[1])
		if err != nil {
			return nil, err
		}
		switch v.Kind() {
		case reflect.Slice:
			i := 0
			if m[2] != "" || v.Len() > 1 {
				if m[2] == "" {
					m[2] = "type"
					if m[3] = e.GetCommon().Default(); m[3] == "" {
						return nil, fmt.Errorf("cldr: type selector or default value needed for element %s", m[1])
					}
				}
				for ; i < v.Len(); i++ {
					vi := v.Index(i)
					key, err := findField(vi.Elem(), m[2])
					if err != nil {
						return nil, err
					}
					key = reflect.Indirect(key)
					if key.Kind() == reflect.String && key.String() == m[3] {
						break
					}
				}
			}
			if i == v.Len() || v.Index(i).IsNil() {
				return nil, fmt.Errorf("no %s found with %s==%s", m[1], m[2], m[3])
			}
			e = v.Index(i).Interface().(Elem)
		case reflect.Ptr:
			if v.IsNil() {
				return nil, fmt.Errorf("cldr: element %q not found within element %q", m[1], e.GetCommon().name)
			}
			var ok bool
			if e, ok = v.Interface().(Elem); !ok {
				return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
			} else if m[2] != "" || m[3] != "" {
				return nil, fmt.Errorf("cldr: no type selector allowed for element %s", m[1])
			}
		default:
			return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
		}
	}
	return e, nil
}

const absPrefix = "//ldml/"

func (cldr *CLDR) resolveAlias(e Elem, src, path string) (res Elem, err error) {
	if src != "locale" {
		if !strings.HasPrefix(path, absPrefix) {
			return nil, fmt.Errorf("cldr: expected absolute path, found %q", path)
		}
		path = path[len(absPrefix):]
		if e, err = cldr.resolve(src); err != nil {
			return nil, err
		}
	}
	return walkXPath(e, path)
}

func (cldr *CLDR) resolveAndMergeAlias(e Elem) error {
	alias := e.GetCommon().Alias
	if alias == nil {
		return nil
	}
	a, err := cldr.resolveAlias(e, alias.Source, alias.Path)
	if err != nil {
		return fmt.Errorf("%v: error evaluating path %q: %v", getPath(e), alias.Path, err)
	}
	// Ensure alias node was already evaluated. TODO: avoid double evaluation.
	err = cldr.resolveAndMergeAlias(a)
	v := reflect.ValueOf(e).Elem()
	for i := iter(reflect.ValueOf(a).Elem()); !i.done(); i.next() {
		if vv := i.value(); vv.Kind() != reflect.Ptr || !vv.IsNil() {
			if _, attr := xmlName(i.field()); !attr {
				v.FieldByIndex(i.index).Set(vv)
			}
		}
	}
	return err
}

func (cldr *CLDR) aliasResolver() visitor {
	return func(v reflect.Value) (err error) {
		if e, ok := v.Addr().Interface().(Elem); ok {
			err = cldr.resolveAndMergeAlias(e)
			if err == nil && blocking[e.GetCommon().name] {
				return stopDescent
			}
		}
		return err
	}
}

// elements within blocking elements do not inherit.
// Taken from CLDR's supplementalMetaData.xml.
var blocking = map[string]bool{
	"identity":         true,
	"supplementalData": true,
	"cldrTest":         true,
	"collation":        true,
	"transform":        true,
}

// Distinguishing attributes affect inheritance; two elements with different
// distinguishing attributes are treated as different for purposes of inheritance,
// except when such attributes occur in the indicated elements.
// Taken from CLDR's supplementalMetaData.xml.
var distinguishing = map[string][]string{
	"key":        nil,
	"request_id": nil,
	"id":         nil,
	"registry":   nil,
	"alt":        nil,
	"iso4217":    nil,
	"iso3166":    nil,
	"mzone":      nil,
	"from":       nil,
	"to":         nil,
	"type": []string{
		"abbreviationFallback",
		"default",
		"mapping",
		"measurementSystem",
		"preferenceOrdering",
	},
	"numberSystem": nil,
}

func in(set []string, s string) bool {
	for _, v := range set {
		if v == s {
			return true
		}
	}
	return false
}

// attrKey computes a key based on the distinguishable attributes of
// an element and it's values.
func attrKey(v reflect.Value, exclude ...string) string {
	parts := []string{}
	ename := v.Interface().(Elem).GetCommon().name
	v = v.Elem()
	for i := iter(v); !i.done(); i.next() {
		if name, attr := xmlName(i.field()); attr {
			if except, ok := distinguishing[name]; ok && !in(exclude, name) && !in(except, ename) {
				v := i.value()
				if v.Kind() == reflect.Ptr {
					v = v.Elem()
				}
				if v.IsValid() {
					parts = append(parts, fmt.Sprintf("%s=%s", name, v.String()))
				}
			}
		}
	}
	sort.Strings(parts)
	return strings.Join(parts, ";")
}

// Key returns a key for e derived from all distinguishing attributes
// except those specified by exclude.
func Key(e Elem, exclude ...string) string {
	return attrKey(reflect.ValueOf(e), exclude...)
}

// linkEnclosing sets the enclosing element as well as the name
// for all sub-elements of child, recursively.
func linkEnclosing(parent, child Elem) {
	child.setEnclosing(parent)
	v := reflect.ValueOf(child).Elem()
	for i := iter(v); !i.done(); i.next() {
		vf := i.value()
		if vf.Kind() == reflect.Slice {
			for j := 0; j < vf.Len(); j++ {
				linkEnclosing(child, vf.Index(j).Interface().(Elem))
			}
		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
			linkEnclosing(child, vf.Interface().(Elem))
		}
	}
}

func setNames(e Elem, name string) {
	e.setName(name)
	v := reflect.ValueOf(e).Elem()
	for i := iter(v); !i.done(); i.next() {
		vf := i.value()
		name, _ = xmlName(i.field())
		if vf.Kind() == reflect.Slice {
			for j := 0; j < vf.Len(); j++ {
				setNames(vf.Index(j).Interface().(Elem), name)
			}
		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
			setNames(vf.Interface().(Elem), name)
		}
	}
}

// deepCopy copies elements of v recursively.  All elements of v that may
// be modified by inheritance are explicitly copied.
func deepCopy(v reflect.Value) reflect.Value {
	switch v.Kind() {
	case reflect.Ptr:
		if v.IsNil() || v.Elem().Kind() != reflect.Struct {
			return v
		}
		nv := reflect.New(v.Elem().Type())
		nv.Elem().Set(v.Elem())
		deepCopyRec(nv.Elem(), v.Elem())
		return nv
	case reflect.Slice:
		nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
		for i := 0; i < v.Len(); i++ {
			deepCopyRec(nv.Index(i), v.Index(i))
		}
		return nv
	}
	panic("deepCopy: must be called with pointer or slice")
}

// deepCopyRec is only called by deepCopy.
func deepCopyRec(nv, v reflect.Value) {
	if v.Kind() == reflect.Struct {
		t := v.Type()
		for i := 0; i < v.NumField(); i++ {
			if name, attr := xmlName(t.Field(i)); name != "" && !attr {
				deepCopyRec(nv.Field(i), v.Field(i))
			}
		}
	} else {
		nv.Set(deepCopy(v))
	}
}

// newNode is used to insert a missing node during inheritance.
func (cldr *CLDR) newNode(v, enc reflect.Value) reflect.Value {
	n := reflect.New(v.Type())
	for i := iter(v); !i.done(); i.next() {
		if name, attr := xmlName(i.field()); name == "" || attr {
			n.Elem().FieldByIndex(i.index).Set(i.value())
		}
	}
	n.Interface().(Elem).GetCommon().setEnclosing(enc.Addr().Interface().(Elem))
	return n
}

// v, parent must be pointers to struct
func (cldr *CLDR) inheritFields(v, parent reflect.Value) (res reflect.Value, err error) {
	t := v.Type()
	nv := reflect.New(t)
	nv.Elem().Set(v)
	for i := iter(v); !i.done(); i.next() {
		vf := i.value()
		f := i.field()
		name, attr := xmlName(f)
		if name == "" || attr {
			continue
		}
		pf := parent.FieldByIndex(i.index)
		if blocking[name] {
			if vf.IsNil() {
				vf = pf
			}
			nv.Elem().FieldByIndex(i.index).Set(deepCopy(vf))
			continue
		}
		switch f.Type.Kind() {
		case reflect.Ptr:
			if f.Type.Elem().Kind() == reflect.Struct {
				if !vf.IsNil() {
					if vf, err = cldr.inheritStructPtr(vf, pf); err != nil {
						return reflect.Value{}, err
					}
					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
					nv.Elem().FieldByIndex(i.index).Set(vf)
				} else if !pf.IsNil() {
					n := cldr.newNode(pf.Elem(), v)
					if vf, err = cldr.inheritStructPtr(n, pf); err != nil {
						return reflect.Value{}, err
					}
					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
					nv.Elem().FieldByIndex(i.index).Set(vf)
				}
			}
		case reflect.Slice:
			vf, err := cldr.inheritSlice(nv.Elem(), vf, pf)
			if err != nil {
				return reflect.Zero(t), err
			}
			nv.Elem().FieldByIndex(i.index).Set(vf)
		}
	}
	return nv, nil
}

func root(e Elem) *LDML {
	for ; e.enclosing() != nil; e = e.enclosing() {
	}
	return e.(*LDML)
}

// inheritStructPtr first merges possible aliases in with v and then inherits
// any underspecified elements from parent.
func (cldr *CLDR) inheritStructPtr(v, parent reflect.Value) (r reflect.Value, err error) {
	if !v.IsNil() {
		e := v.Interface().(Elem).GetCommon()
		alias := e.Alias
		if alias == nil && !parent.IsNil() {
			alias = parent.Interface().(Elem).GetCommon().Alias
		}
		if alias != nil {
			a, err := cldr.resolveAlias(v.Interface().(Elem), alias.Source, alias.Path)
			if a != nil {
				if v, err = cldr.inheritFields(v.Elem(), reflect.ValueOf(a).Elem()); err != nil {
					return reflect.Value{}, err
				}
			}
		}
		if !parent.IsNil() {
			return cldr.inheritFields(v.Elem(), parent.Elem())
		}
	} else if parent.IsNil() {
		panic("should not reach here")
	}
	return v, nil
}

// Must be slice of struct pointers.
func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, err error) {
	t := v.Type()
	index := make(map[string]reflect.Value)
	if !v.IsNil() {
		for i := 0; i < v.Len(); i++ {
			vi := v.Index(i)
			key := attrKey(vi)
			index[key] = vi
		}
	}
	if !parent.IsNil() {
		for i := 0; i < parent.Len(); i++ {
			vi := parent.Index(i)
			key := attrKey(vi)
			if w, ok := index[key]; ok {
				index[key], err = cldr.inheritStructPtr(w, vi)
			} else {
				n := cldr.newNode(vi.Elem(), enc)
				index[key], err = cldr.inheritStructPtr(n, vi)
			}
			index[key].Interface().(Elem).setEnclosing(enc.Addr().Interface().(Elem))
			if err != nil {
				return v, err
			}
		}
	}
	keys := make([]string, 0, len(index))
	for k, _ := range index {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	sl := reflect.MakeSlice(t, len(index), len(index))
	for i, k := range keys {
		sl.Index(i).Set(index[k])
	}
	return sl, nil
}

func parentLocale(loc string) string {
	parts := strings.Split(loc, "_")
	if len(parts) == 1 {
		return "root"
	}
	parts = parts[:len(parts)-1]
	key := strings.Join(parts, "_")
	return key
}

func (cldr *CLDR) resolve(loc string) (res *LDML, err error) {
	if r := cldr.resolved[loc]; r != nil {
		return r, nil
	}
	x := cldr.RawLDML(loc)
	if x == nil {
		return nil, fmt.Errorf("cldr: unknown locale %q", loc)
	}
	var v reflect.Value
	if loc == "root" {
		x = deepCopy(reflect.ValueOf(x)).Interface().(*LDML)
		linkEnclosing(nil, x)
		err = cldr.aliasResolver().visit(x)
	} else {
		key := parentLocale(loc)
		var parent *LDML
		for ; cldr.locale[key] == nil; key = parentLocale(key) {
		}
		if parent, err = cldr.resolve(key); err != nil {
			return nil, err
		}
		v, err = cldr.inheritFields(reflect.ValueOf(x).Elem(), reflect.ValueOf(parent).Elem())
		x = v.Interface().(*LDML)
		linkEnclosing(nil, x)
	}
	if err != nil {
		return nil, err
	}
	cldr.resolved[loc] = x
	return x, err
}

// finalize finalizes the initialization of the raw LDML structs.  It also
// removed unwanted fields, as specified by filter, so that they will not
// be unnecessarily evaluated.
func (cldr *CLDR) finalize(filter []string) {
	for _, x := range cldr.locale {
		if filter != nil {
			v := reflect.ValueOf(x).Elem()
			t := v.Type()
			for i := 0; i < v.NumField(); i++ {
				f := t.Field(i)
				name, _ := xmlName(f)
				if name != "" && name != "identity" && !in(filter, name) {
					v.Field(i).Set(reflect.Zero(f.Type))
				}
			}
		}
		linkEnclosing(nil, x) // for resolving aliases and paths
		setNames(x, "ldml")
	}
}
