// Copyright 2016 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 vdl

import (
	"errors"
	"fmt"
	"reflect"
)

var (
	errReadMustReflect       = errors.New("vdl: read must be handled via reflection")
	errReadIntoNilValue      = errors.New("vdl: read into nil value")
	errReadReflectCantSet    = errors.New("vdl: read into unsettable reflect.Value")
	errReadAnyAlreadyStarted = errors.New("vdl: read into any after StartValue called")
	errReadAnyInterfaceOnly  = errors.New("vdl: read into any only supported for interfaces")
)

// Read uses dec to decode a value into v, calling VDLRead methods and fast
// compiled readers when available, and using reflection otherwise.  This is
// basically an all-purpose VDLRead implementation.
func Read(dec Decoder, v interface{}) error {
	if v == nil {
		return errReadIntoNilValue
	}
	rv := reflect.ValueOf(v)
	if rv.Kind() == reflect.Ptr && !rv.IsNil() {
		// Fastpath check for non-reflect support.  Unfortunately we must use
		// reflection to detect the case where v is a nil pointer, which returns an
		// error in ReadReflect.
		//
		// TODO(toddw): If reflection is too slow, add the nil pointer check to all
		// VDLRead methods, as well as other readNonReflect cases below.
		if err := readNonReflect(dec, false, v); err != errReadMustReflect {
			return err
		}
	}
	return ReadReflect(dec, rv)
}

func readNonReflect(dec Decoder, calledStart bool, v interface{}) error {
	switch x := v.(type) {
	case Reader:
		// Reader handles code-generated VDLRead methods, and special-cases such as
		// vdl.Value and vom.RawBytes.
		if calledStart {
			dec.IgnoreNextStartValue()
		}
		return x.VDLRead(dec)
	case **Type:
		// Special-case type decoding, since we must assign the hash-consed pointer
		// for correctness, rather than filling in a newly-created Type.
		if calledStart {
			dec.IgnoreNextStartValue()
		}
		var err error
		*x, err = dec.ReadValueTypeObject()
		return err

		// TODO(toddw): Consider adding common-cases as performance optimizations.
	}
	return errReadMustReflect
}

// ReadReflect is like Read, but takes a reflect.Value argument.
func ReadReflect(dec Decoder, rv reflect.Value) error {
	if !rv.IsValid() {
		return errReadIntoNilValue
	}
	if !rv.CanSet() && rv.Kind() == reflect.Ptr && !rv.IsNil() {
		// Dereference the pointer a single time to make rv settable.
		rv = rv.Elem()
	}
	if !rv.CanSet() {
		return errReadReflectCantSet
	}
	tt, err := TypeFromReflect(rv.Type())
	if err != nil {
		return err
	}
	return readReflect(dec, false, rv, tt)
}

// readReflect uses dec to decode a value into rv, which has VDL type tt.  On
// success we guarantee that StartValue / FinishValue has been called on dec.
// If calledStart is true, StartValue has already been called.
func readReflect(dec Decoder, calledStart bool, rv reflect.Value, tt *Type) error {
	// Handle decoding into an any rv value first, since vom.RawBytes.VDLRead
	// doesn't support IgnoreNextStartValue, and requires that StartValue hasn't
	// been called yet.  Note that cases where the dec value is any but the rv
	// value isn't any will pass through.
	if tt == AnyType {
		return readIntoAny(dec, calledStart, rv)
	}
	// Handle optional types, which need StartValue to be called first to
	// determine whether the decoded value is nil.
	if tt.Kind() == Optional {
		if !calledStart {
			calledStart = true
			if err := dec.StartValue(tt); err != nil {
				return err
			}
		}
		// Handle nil decoded values next, to simplify the rest of the cases.  This
		// handles cases where the dec value is either any(nil) or optional(nil).
		if dec.IsNil() {
			return readFromNil(dec, rv, tt)
		}
	}
	// Now we know that rv isn't optional.  Flatten pointers and check for fast
	// non-reflect support.
	rv = rvFlattenPointers(rv)
	if err := readNonReflect(dec, calledStart, rv.Addr().Interface()); err != errReadMustReflect {
		return err
	}
	// Handle native types, which need the ToNative conversion.  Notice that rv is
	// never a pointer here, so we don't support native pointer types.  In theory
	// we could support native pointer types, but they're complicated and will
	// probably slow everything down.
	//
	// TODO(toddw): Investigate support for native pointer types.
	if ni := nativeInfoFromNative(rv.Type()); ni != nil {
		rvWire := reflect.New(ni.WireType).Elem()
		if err := readReflect(dec, calledStart, rvWire, tt); err != nil {
			return err
		}
		return ni.ToNative(rvWire, rv.Addr())
		// NOTE: readReflect guarantees that FinishValue has already been called.
	}
	tt = tt.NonOptional()
	// Handle scalar wire values.
	if ttReadIntoScalar(tt) {
		if calledStart {
			dec.IgnoreNextStartValue()
		}
		return readValueScalar(dec, rv, tt)
	}
	// Handle bytes wire values.
	if tt.IsBytes() {
		if calledStart {
			dec.IgnoreNextStartValue()
		}
		return readValueBytes(dec, rv, tt)
	}
	// Handle composite wire values.
	if !calledStart {
		if err := dec.StartValue(tt); err != nil {
			return err
		}
	}
	var err error
	switch tt.Kind() {
	case Array:
		err = readFixedLenList(dec, "array", rv.Len(), rv, tt)
	case List:
		err = readList(dec, rv, tt)
	case Set:
		err = readSet(dec, rv, tt)
	case Map:
		err = readMap(dec, rv, tt)
	case Struct:
		err = readStruct(dec, rv, tt)
	case Union:
		err = readUnion(dec, rv, tt)
	default:
		// Note that both Any and Optional were handled in readIntAny, and
		// TypeObject was handled via the readNonReflect special-case.
		return fmt.Errorf("vdl: Read unhandled type %v %v", rv.Type(), tt)
	}
	if err != nil {
		return err
	}
	return dec.FinishValue()
}

// settable exists to avoid a call to reflect.Call() to invoke Set()
// which results in an allocation
type settable interface {
	Set(string) error
}

// readIntoAny uses dec to decode a value into rv, which has VDL type any.
func readIntoAny(dec Decoder, calledStart bool, rv reflect.Value) error {
	if calledStart {
		// The existing code ensures that calledStart is always false here, since
		// readReflect(dec, true, ...) is only called in situations where it's
		// impossible to call readIntoAny.  E.g. it's called later in this function,
		// which never calls it with another any type.  If we did, we'd have a vdl
		// any(any), which isn't allowed.  This error tries to prevent future
		// changes that will break this requirement.
		//
		// The requirement is mandated by vom.RawBytes.VDLRead, which doesn't handle
		// IgnoreNextStartValue.
		return errReadAnyAlreadyStarted
	}
	// Flatten pointers and check for fast non-reflect support, which handles
	// vdl.Value and vom.RawBytes, and any other special-cases.
	rv = rvFlattenPointers(rv)
	if err := readNonReflect(dec, false, rv.Addr().Interface()); err != errReadMustReflect {
		return err
	}
	// The only case left is to handle interfaces.  We allow decoding into
	// all interfaces, including interface{}.
	if rv.Kind() != reflect.Interface {
		return errReadAnyInterfaceOnly
	}
	if err := dec.StartValue(AnyType); err != nil {
		return err
	}
	// Handle decoding any(nil) by setting the rv interface to nil.  Note that the
	// only case where dec.Type() is AnyType is when the value is any(nil).
	if dec.Type() == AnyType {
		if !rv.IsNil() {
			rv.Set(reflect.Zero(rv.Type()))
		}
		return dec.FinishValue()
	}
	// Lookup the reflect type based on the decoder type, and create a new value
	// to decode into.  If the dec value is optional, ensure that we lookup based
	// on an optional type.  Note that if the dec value is nil, dec.Type() is
	// already optional, so rtDecode will already be a pointer.
	ttDecode := dec.Type()
	if dec.IsOptional() && !dec.IsNil() {
		ttDecode = OptionalType(ttDecode)
	}
	rtDecode := typeToReflectNew(ttDecode)
	// Handle top-level "v.io/v23/vdl.WireError" types.  TypeToReflect will find
	// vdl.WireError based on regular wire type registration, and will find the Go
	// error interface based on regular native type registration, and these are
	// fine for nested error types.
	//
	// But this is the case where we're decoding into a top-level Go interface,
	// and we'll lose type information if the dec value is nil.  So instead we
	// return the registered verror.E type.  Examples:
	//
	//   ttDecode  ->  rtDecode
	//   -----------------------
	//   WireError     verror.E
	//   ?WireError    *verror.E
	//   []WireError   []vdl.WireError (1)
	//   []?WireError  []error
	//
	// TODO(toddw): The (1) case above is weird; we would like to return verror.E,
	// but that's hard because the native conversion we've registered doesn't
	// currently include the verror.E type:
	//
	//    ToNative(wire *vdl.WireError, native *error)
	//    FromNative(wire **vdl.WireError, native error)
	//
	// We could make this more consistent by registering a pair of conversion
	// functions instead:
	//
	//    ToNative(wire vdl.WireError, native *verror.E)
	//    FromNative(wire *vdl.WireError, native verror.E)
	//
	//    ToNative(wire *verror.E, native *error)
	//    FromNative(wire **verror.E, native error)
	if ttDecode.NonOptional().Name() == ErrorType.Elem().Name() {
		if ni, err := nativeInfoForError(); err == nil {
			if ttDecode.Kind() == Optional {
				rtDecode = reflect.PtrTo(ni.NativeType)
			} else {
				rtDecode = ni.NativeType
			}
		}
	}
	if rtDecode == nil {
		return fmt.Errorf("vdl: %v not registered, either call vdl.Register, or use vdl.Value or vom.RawBytes instead", dec.Type())
	}
	if !rtDecode.Implements(rv.Type()) {
		return fmt.Errorf("vdl: %v doesn't implement %v", rtDecode, rv.Type())
	}
	// Handle both nil and non-nil values by decoding into rvDecode, and setting
	// rv.  Both nil and non-nil values are handled in the readReflect call.
	rvDecode := reflect.New(rtDecode).Elem()
	if err := readReflect(dec, true, rvDecode, ttDecode); err != nil {
		return err
	}
	rv.Set(rvDecode)
	// NOTE: readReflect guarantees that FinishValue has already been called.
	return nil
}

// readFromNil uses dec to decode a nil value into rv, which has VDL type tt.
// The value in dec might be either any(nil) or optional(nil).
//
// REQUIRES: dec.IsNil() && tt != AnyType
func readFromNil(dec Decoder, rv reflect.Value, tt *Type) error {
	if tt.Kind() != Optional {
		return fmt.Errorf("vdl: can't decode nil into non-optional %v", tt)
	}
	// Flatten pointers until we have a single pointer left, or there were no
	// pointers to begin with.
	rt := rv.Type()
	for rt.Kind() == reflect.Ptr && rt.Elem().Kind() == reflect.Ptr {
		if rv.IsNil() {
			rv.Set(reflect.New(rt.Elem()))
		}
		rv, rt = rv.Elem(), rt.Elem()
	}
	// Handle tricky cases where rv is a native type.
	if handled, err := readFromNilNative(dec, rv, tt); handled {
		return err
	}
	// Now handle the simple case: rv has one pointer left, and should be set to a
	// nil pointer.
	if rt.Kind() != reflect.Ptr {
		return fmt.Errorf("vdl: can't decode nil into non-pointer %v optional %v", rt, tt)
	}
	if !rv.IsNil() {
		rv.Set(reflect.Zero(rt))
	}
	return dec.FinishValue()
}

// readFromNilNative handles tricky cases where rv is a native type.  Returns
// true if rv is a native type and was handled, otherwise returns false.
//
// REQUIRES: rv.Type() has at most one pointer.
func readFromNilNative(dec Decoder, rv reflect.Value, tt *Type) (bool, error) {
	var ni *nativeInfo
	if rt := rv.Type(); rt.Kind() != reflect.Ptr {
		// Handle the case where rv isn't a pointer; e.g. the Go error interface is
		// a non-pointer native type, and is handled here.
		ni = nativeInfoFromNative(rt)
	} else {
		// Handle the case where rv is a pointer, and the elem is a native type.
		// E.g. *error is handled here.  Note that we don't support native pointer
		// types; see comments at other calls to nativeInfoFromNative.
		ni = nativeInfoFromNative(rt.Elem())
		if ni != nil {
			if rv.IsNil() {
				rv.Set(reflect.New(rt.Elem()))
			}
			rv = rv.Elem()
		}
	}
	if ni != nil {
		// Handle the native type from either case above.  At this point, rv is the
		// native type and isn't a nil pointer.
		rvWire := reflect.New(ni.WireType).Elem()
		if err := readReflect(dec, true, rvWire, tt); err != nil {
			return true, err
		}
		return true, ni.ToNative(rvWire, rv.Addr())
		// NOTE: readReflect guarantees that FinishValue has already been called.
	}
	return false, nil
}

func ttReadIntoScalar(tt *Type) bool {
	switch tt.Kind() {
	case Bool, String, Enum, Byte, Uint16, Uint32, Uint64, Int8, Int16, Int32, Int64, Float32, Float64:
		return true
	}
	return false
}

func readValueScalar(dec Decoder, rv reflect.Value, tt *Type) error {
	switch kind := tt.Kind(); kind {
	case Bool:
		value, err := dec.ReadValueBool()
		if err != nil {
			return err
		}
		rv.SetBool(value)
		return nil
	case String:
		value, err := dec.ReadValueString()
		if err != nil {
			return err
		}
		rv.SetString(value)
		return nil
	case Enum:
		value, err := dec.ReadValueString()
		if err != nil {
			return err
		}
		return rv.Addr().Interface().(settable).Set(value)
	case Byte, Uint16, Uint32, Uint64:
		value, err := dec.ReadValueUint(kind.BitLen())
		if err != nil {
			return err
		}
		rv.SetUint(value)
		return nil
	case Int8, Int16, Int32, Int64:
		value, err := dec.ReadValueInt(kind.BitLen())
		if err != nil {
			return err
		}
		rv.SetInt(value)
		return nil
	case Float32, Float64:
		value, err := dec.ReadValueFloat(kind.BitLen())
		if err != nil {
			return err
		}
		rv.SetFloat(value)
		return nil
	}
	return fmt.Errorf("vdl: readValueScalar called on non-scalar %v, %v", tt, rv.Type())
}

func readNextEntryScalar(dec Decoder, rv reflect.Value, tt *Type) (bool, error) {
	switch kind := tt.Kind(); kind {
	case Bool:
		switch done, value, err := dec.NextEntryValueBool(); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			rv.SetBool(value)
			return false, nil
		}
	case String:
		switch done, value, err := dec.NextEntryValueString(); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			rv.SetString(value)
			return false, nil
		}
	case Enum:
		switch done, value, err := dec.NextEntryValueString(); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			return false, rv.Addr().Interface().(settable).Set(value)
		}
	case Byte, Uint16, Uint32, Uint64:
		switch done, value, err := dec.NextEntryValueUint(kind.BitLen()); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			rv.SetUint(value)
			return false, nil
		}
	case Int8, Int16, Int32, Int64:
		switch done, value, err := dec.NextEntryValueInt(kind.BitLen()); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			rv.SetInt(value)
			return false, nil
		}
	case Float32, Float64:
		switch done, value, err := dec.NextEntryValueFloat(kind.BitLen()); {
		case err != nil:
			return false, err
		case done:
			return true, nil
		default:
			rv.SetFloat(value)
			return false, nil
		}
	}
	return false, fmt.Errorf("vdl: readNextEntryScalar called on non-scalar %v, %v", tt, rv.Type())
}

func readValueBytes(dec Decoder, rv reflect.Value, tt *Type) error {
	kind := tt.Kind()
	// Go doesn't allow type conversions from []MyByte to []byte, but the reflect
	// package does let us perform this conversion.  We slice arrays so that we
	// can fill them in directly.
	fixedLen, needAssign := -1, false
	var fillPtr *[]byte
	switch {
	case kind == Array:
		fixedLen = tt.Len()
		tmp := rv.Slice(0, fixedLen).Bytes()
		fillPtr = &tmp
	case tt.Name() != "" || tt.Elem() != ByteType:
		fillPtr = new([]byte)
		needAssign = true
	default: // rv has type []byte
		fillPtr = rv.Addr().Interface().(*[]byte)
	}
	if err := dec.ReadValueBytes(fixedLen, fillPtr); err != nil {
		return err
	}
	if needAssign {
		rv.SetBytes(*fillPtr)
	}
	return nil
}

func readFixedLenList(dec Decoder, name string, len int, rv reflect.Value, tt *Type) error {
	ttElem := tt.Elem()
	if ttReadIntoScalar(ttElem) {
		// Handle scalar element fastpath.
		for index := 0; index < len; index++ {
			switch done, err := readNextEntryScalar(dec, rv.Index(index), ttElem); {
			case err != nil:
				return err
			case done:
				return fmt.Errorf("vdl: short %s, got len %d < %d %v", name, index, len, rv.Type())
			}
		}
	} else {
		// Handle non-scalar elements.
		for index := 0; index < len; index++ {
			switch done, err := dec.NextEntry(); {
			case err != nil:
				return err
			case done:
				return fmt.Errorf("vdl: short %s, got len %d < %d %v", name, index, len, rv.Type())
			}
			if err := readReflect(dec, false, rv.Index(index), ttElem); err != nil {
				return err
			}
		}
	}
	switch done, err := dec.NextEntry(); {
	case err != nil:
		return err
	case !done:
		return fmt.Errorf("vdl: long %s, got len > %d %v", name, len, rv.Type())
	}
	return nil
}

func readList(dec Decoder, rv reflect.Value, tt *Type) error {
	rt := rv.Type()
	rtElem, ttElem := rt.Elem(), tt.Elem()
	if len := dec.LenHint(); len > 0 {
		// Handle fixed-length fastpath.
		rv.Set(reflect.MakeSlice(rt, len, len))
		return readFixedLenList(dec, "list", len, rv, tt)
	}
	// TODO(toddw): Make progressively larger slices, rather than creating each
	// element one at a time.
	rv.Set(reflect.Zero(rt))
	if ttReadIntoScalar(ttElem) {
		// Handle scalar element fastpath.
		for {
			rvElem := reflect.New(rtElem).Elem()
			switch done, err := readNextEntryScalar(dec, rvElem, ttElem); {
			case err != nil:
				return err
			case done:
				return nil
			}
			rv.Set(reflect.Append(rv, rvElem))
		}
	}
	// Handle non-scalar elements.
	for {
		switch done, err := dec.NextEntry(); {
		case err != nil:
			return err
		case done:
			return nil
		}
		rvElem := reflect.New(rtElem).Elem()
		if err := readReflect(dec, false, rvElem, ttElem); err != nil {
			return err
		}
		rv.Set(reflect.Append(rv, rvElem))
	}
}

var rvEmptyStruct = reflect.ValueOf(struct{}{})

func readSet(dec Decoder, rv reflect.Value, tt *Type) error {
	rt := rv.Type()
	rtKey, ttKey := rt.Key(), tt.Key()
	tmpSet, isNil := reflect.Zero(rt), true
	if ttReadIntoScalar(ttKey) {
		// Handle scalar key fastpath.
		for {
			rvKey := reflect.New(rtKey).Elem()
			switch done, err := readNextEntryScalar(dec, rvKey, ttKey); {
			case err != nil:
				return err
			case done:
				rv.Set(tmpSet)
				return nil
			}
			if isNil {
				tmpSet, isNil = reflect.MakeMap(rt), false
			}
			tmpSet.SetMapIndex(rvKey, rvEmptyStruct)
		}
	}
	// Handle non-scalar elements.
	for {
		switch done, err := dec.NextEntry(); {
		case err != nil:
			return err
		case done:
			rv.Set(tmpSet)
			return nil
		}
		rvKey := reflect.New(rtKey).Elem()
		if err := readReflect(dec, false, rvKey, ttKey); err != nil {
			return err
		}
		if isNil {
			tmpSet, isNil = reflect.MakeMap(rt), false
		}
		tmpSet.SetMapIndex(rvKey, rvEmptyStruct)
	}
}

func readMap(dec Decoder, rv reflect.Value, tt *Type) error {
	rt := rv.Type()
	rtKey, ttKey := rt.Key(), tt.Key()
	rtElem, ttElem := rt.Elem(), tt.Elem()
	tmpMap, isNil := reflect.Zero(rt), true
	if ttReadIntoScalar(ttKey) {
		// Handle scalar key fastpath.
		for {
			rvKey := reflect.New(rtKey).Elem()
			switch done, err := readNextEntryScalar(dec, rvKey, ttKey); {
			case err != nil:
				return err
			case done:
				rv.Set(tmpMap)
				return nil
			}
			rvElem := reflect.New(rtElem).Elem()
			if err := readReflect(dec, false, rvElem, ttElem); err != nil {
				return err
			}
			if isNil {
				tmpMap, isNil = reflect.MakeMap(rt), false
			}
			tmpMap.SetMapIndex(rvKey, rvElem)
		}
	}
	// Handle non-scalar keys.
	for {
		switch done, err := dec.NextEntry(); {
		case err != nil:
			return err
		case done:
			rv.Set(tmpMap)
			return nil
		}
		rvKey := reflect.New(rtKey).Elem()
		if err := readReflect(dec, false, rvKey, ttKey); err != nil {
			return err
		}
		rvElem := reflect.New(rtElem).Elem()
		if err := readReflect(dec, false, rvElem, ttElem); err != nil {
			return err
		}
		if isNil {
			tmpMap, isNil = reflect.MakeMap(rt), false
		}
		tmpMap.SetMapIndex(rvKey, rvElem)
	}
}

func readStruct(dec Decoder, rv reflect.Value, tt *Type) error {
	rt := rv.Type()
	// Reset to the zero struct, since fields may be missing.
	//
	// TODO(toddw): Avoid repeated zero-setting of nested structs.
	rvZero, err := rvZeroValue(rt, tt)
	if err != nil {
		return err
	}
	rv.Set(rvZero)
	for {
		name, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case name == "":
			return nil
		}
		switch ttField, index := tt.FieldByName(name); {
		case index != -1:
			rvField := rv.FieldByName(name)
			if err := readReflect(dec, false, rvField, ttField.Type); err != nil {
				return err
			}
		default:
			if err := dec.SkipValue(); err != nil {
				return err
			}
		}
	}
}

func readUnion(dec Decoder, rv reflect.Value, tt *Type) error {
	rt := rv.Type()
	name, err := dec.NextField()
	switch {
	case err != nil:
		return err
	case name == "":
		return fmt.Errorf("missing field in union %v, from %v", rt, dec.Type())
	}
	ttField, index := tt.FieldByName(name)
	if index == -1 {
		return fmt.Errorf("field %q not in union %v, from %v", name, rt, dec.Type())
	}
	// We have a union interface.  Create a new field based on its rep type, fill
	// in its value, and assign the field to the interface.
	ri, _, err := deriveReflectInfo(rt)
	if err != nil {
		return err
	}
	rvField := reflect.New(ri.UnionFields[index].RepType).Elem()
	if err := readReflect(dec, false, rvField.Field(0), ttField.Type); err != nil {
		return err
	}
	rv.Set(rvField)
	switch name, err := dec.NextField(); {
	case err != nil:
		return err
	case name != "":
		return fmt.Errorf("extra field %q in union %v, from %v", name, rt, dec.Type())
	}
	return nil
}
