/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mo

import (
	"fmt"
	"reflect"
	"regexp"
	"strings"
	"sync"

	"github.com/vmware/govmomi/vim25/types"
)

type typeInfo struct {
	typ reflect.Type

	// Field indices of "Self" field.
	self []int

	// Map property names to field indices.
	props map[string][]int
}

var typeInfoLock sync.RWMutex
var typeInfoMap = make(map[string]*typeInfo)

func typeInfoForType(tname string) *typeInfo {
	typeInfoLock.RLock()
	ti, ok := typeInfoMap[tname]
	typeInfoLock.RUnlock()

	if ok {
		return ti
	}

	// Create new typeInfo for type.
	if typ, ok := t[tname]; !ok {
		panic("unknown type: " + tname)
	} else {
		// Multiple routines may race to set it, but the result is the same.
		typeInfoLock.Lock()
		ti = newTypeInfo(typ)
		typeInfoMap[tname] = ti
		typeInfoLock.Unlock()
	}

	return ti
}

func newTypeInfo(typ reflect.Type) *typeInfo {
	t := typeInfo{
		typ:   typ,
		props: make(map[string][]int),
	}

	t.build(typ, "", []int{})

	return &t
}

var managedObjectRefType = reflect.TypeOf((*types.ManagedObjectReference)(nil)).Elem()

func buildName(fn string, f reflect.StructField) string {
	if fn != "" {
		fn += "."
	}

	motag := f.Tag.Get("mo")
	if motag != "" {
		return fn + motag
	}

	xmltag := f.Tag.Get("xml")
	if xmltag != "" {
		tokens := strings.Split(xmltag, ",")
		if tokens[0] != "" {
			return fn + tokens[0]
		}
	}

	return ""
}

func (t *typeInfo) build(typ reflect.Type, fn string, fi []int) {
	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
	}

	if typ.Kind() != reflect.Struct {
		panic("need struct")
	}

	for i := 0; i < typ.NumField(); i++ {
		f := typ.Field(i)
		ftyp := f.Type

		// Copy field indices so they can be passed along.
		fic := make([]int, len(fi)+1)
		copy(fic, fi)
		fic[len(fi)] = i

		// Recurse into embedded field.
		if f.Anonymous {
			t.build(ftyp, fn, fic)
			continue
		}

		// Top level type has a "Self" field.
		if f.Name == "Self" && ftyp == managedObjectRefType {
			t.self = fic
			continue
		}

		fnc := buildName(fn, f)
		if fnc == "" {
			continue
		}

		t.props[fnc] = fic

		// Dereference pointer.
		if ftyp.Kind() == reflect.Ptr {
			ftyp = ftyp.Elem()
		}

		// Slices are not addressable by `foo.bar.qux`.
		if ftyp.Kind() == reflect.Slice {
			continue
		}

		// Skip the managed reference type.
		if ftyp == managedObjectRefType {
			continue
		}

		// Recurse into structs.
		if ftyp.Kind() == reflect.Struct {
			t.build(ftyp, fnc, fic)
		}
	}
}

var nilValue reflect.Value

// assignValue assignes a value 'pv' to the struct pointed to by 'val', given a
// slice of field indices. It recurses into the struct until it finds the field
// specified by the indices. It creates new values for pointer types where
// needed.
func assignValue(val reflect.Value, fi []int, pv reflect.Value) {
	// Create new value if necessary.
	if val.Kind() == reflect.Ptr {
		if val.IsNil() {
			val.Set(reflect.New(val.Type().Elem()))
		}

		val = val.Elem()
	}

	rv := val.Field(fi[0])
	fi = fi[1:]
	if len(fi) == 0 {
		if pv == nilValue {
			pv = reflect.Zero(rv.Type())
			rv.Set(pv)
			return
		}
		rt := rv.Type()
		pt := pv.Type()

		// If type is a pointer, create new instance of type.
		if rt.Kind() == reflect.Ptr {
			rv.Set(reflect.New(rt.Elem()))
			rv = rv.Elem()
			rt = rv.Type()
		}

		// If the target type is a slice, but the source is not, deference any ArrayOfXYZ type
		if rt.Kind() == reflect.Slice && pt.Kind() != reflect.Slice {
			if pt.Kind() == reflect.Ptr {
				pv = pv.Elem()
				pt = pt.Elem()
			}

			m := arrayOfRegexp.FindStringSubmatch(pt.Name())
			if len(m) > 0 {
				pv = pv.FieldByName(m[1]) // ArrayOfXYZ type has single field named XYZ
				pt = pv.Type()

				if !pv.IsValid() {
					panic(fmt.Sprintf("expected %s type to have field %s", m[0], m[1]))
				}
			}
		}

		// If type is an interface, check if pv implements it.
		if rt.Kind() == reflect.Interface && !pt.Implements(rt) {
			// Check if pointer to pv implements it.
			if reflect.PtrTo(pt).Implements(rt) {
				npv := reflect.New(pt)
				npv.Elem().Set(pv)
				pv = npv
				pt = pv.Type()
			} else {
				panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
			}
		} else if rt.Kind() == reflect.Struct && pt.Kind() == reflect.Ptr {
			pv = pv.Elem()
			pt = pv.Type()
		}

		if pt.AssignableTo(rt) {
			rv.Set(pv)
		} else if rt.ConvertibleTo(pt) {
			rv.Set(pv.Convert(rt))
		} else {
			panic(fmt.Sprintf("cannot assign %q (%s) to %q (%s)", rt.Name(), rt.Kind(), pt.Name(), pt.Kind()))
		}

		return
	}

	assignValue(rv, fi, pv)
}

var arrayOfRegexp = regexp.MustCompile("ArrayOf(.*)$")

// LoadObjectFromContent loads properties from the 'PropSet' field in the
// specified ObjectContent value into the value it represents, which is
// returned as a reflect.Value.
func (t *typeInfo) LoadFromObjectContent(o types.ObjectContent) (reflect.Value, error) {
	v := reflect.New(t.typ)
	assignValue(v, t.self, reflect.ValueOf(o.Obj))

	for _, p := range o.PropSet {
		rv, ok := t.props[p.Name]
		if !ok {
			continue
		}
		assignValue(v, rv, reflect.ValueOf(p.Val))
	}

	return v, nil
}
