/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 hessian

import (
	"io"
	"reflect"
	"strings"
	"sync"
)

import (
	perrors "github.com/pkg/errors"
)

// get @v go struct name
func typeof(v interface{}) string {
	return reflect.TypeOf(v).String()
}

/////////////////////////////////////////
// map/object
/////////////////////////////////////////

//class-def  ::= 'C' string int string* //  mandatory type string, the number of fields, and the field names.
//object     ::= 'O' int value* // class-def id, value list
//           ::= [x60-x6f] value* // class-def id, value list
//
//Object serialization
//
//class Car {
//  String color;
//  String model;
//}
//
//out.writeObject(new Car("red", "corvette"));
//out.writeObject(new Car("green", "civic"));
//
//---
//
//C                        # object definition (#0)
//  x0b example.Car        # type is example.Car
//  x92                    # two fields
//  x05 color              # color field name
//  x05 model              # model field name
//
//O                        # object def (long form)
//  x90                    # object definition #0
//  x03 red                # color field value
//  x08 corvette           # model field value
//
//x60                      # object def #0 (short form)
//  x05 green              # color field value
//  x05 civic              # model field value
//
//enum Color {
//  RED,
//  GREEN,
//  BLUE,
//}
//
//out.writeObject(Color.RED);
//out.writeObject(Color.GREEN);
//out.writeObject(Color.BLUE);
//out.writeObject(Color.GREEN);
//
//---
//
//C                         # class definition #0
//  x0b example.Color       # type is example.Color
//  x91                     # one field
//  x04 name                # enumeration field is "name"
//
//x60                       # object #0 (class def #0)
//  x03 RED                 # RED value
//
//x60                       # object #1 (class def #0)
//  x90                     # object definition ref #0
//  x05 GREEN               # GREEN value
//
//x60                       # object #2 (class def #0)
//  x04 BLUE                # BLUE value
//
//x51 x91                   # object ref #1, i.e. Color.GREEN
func (e *Encoder) encObject(v interface{}) error {
	var (
		ok     bool
		i      int
		idx    int
		num    int
		err    error
		clsDef *classInfo
	)
	pojo, isPojo := v.(POJO)
	vv := reflect.ValueOf(v)

	// get none pojo JavaClassName
	var nonePojoJavaName string
	if !isPojo {
		s, ok := loadPOJORegistry(vv.Type().String())
		if !ok {
			return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
		}
		nonePojoJavaName = s.javaName
	}

	// check ref
	if n, ok := e.checkRefMap(vv); ok {
		e.buffer = encRef(e.buffer, n)
		return nil
	}

	vv = UnpackPtr(vv)
	// check nil pointer
	if !vv.IsValid() {
		e.buffer = EncNull(e.buffer)
		return nil
	}

	// write object definition
	idx = -1
	for i = range e.classInfoList {
		if isPojo && pojo.JavaClassName() == e.classInfoList[i].javaName || !isPojo && nonePojoJavaName == e.classInfoList[i].javaName {
			idx = i
			break
		}
	}

	if idx == -1 {
		idx, ok = checkPOJORegistry(typeof(v))
		if !ok {
			if reflect.TypeOf(v).Implements(javaEnumType) {
				idx = RegisterJavaEnum(v.(POJOEnum))
			} else if isPojo {
				idx = RegisterPOJO(pojo)
			} else {
				return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
			}
		}
		_, clsDef, err = getStructDefByIndex(idx)
		if err != nil {
			return perrors.WithStack(err)
		}

		idx = len(e.classInfoList)
		e.classInfoList = append(e.classInfoList, clsDef)
		e.buffer = append(e.buffer, clsDef.buffer...)
	}

	// write object instance
	if byte(idx) <= OBJECT_DIRECT_MAX {
		e.buffer = encByte(e.buffer, byte(idx)+BC_OBJECT_DIRECT)
	} else {
		e.buffer = encByte(e.buffer, BC_OBJECT)
		e.buffer = encInt32(e.buffer, int32(idx))
	}

	if reflect.TypeOf(v).Implements(javaEnumType) {
		e.buffer = encString(e.buffer, v.(POJOEnum).String())
		return nil
	}

	structs := []reflect.Value{vv}
	for len(structs) > 0 {
		vv := structs[0]
		vvt := vv.Type()
		num = vv.NumField()
		for i = 0; i < num; i++ {
			tf := vvt.Field(i)
			// skip unexported anonymous field
			if tf.PkgPath != "" {
				continue
			}

			// skip ignored field
			if tag, _ := tf.Tag.Lookup(tagIdentifier); tag == `-` {
				continue
			}

			field := vv.Field(i)
			if tf.Anonymous && field.Kind() == reflect.Struct {
				structs = append(structs, field)
				continue
			}

			if err = e.Encode(field.Interface()); err != nil {
				fieldName := field.Type().String()
				return perrors.Wrapf(err, "failed to encode field: %s, %+v", fieldName, field.Interface())
			}
		}

		structs = structs[1:]
	}

	return nil
}

/////////////////////////////////////////
// Object
/////////////////////////////////////////

//class-def  ::= 'C' string int string* //  mandatory type string, the number of fields, and the field names.
//object     ::= 'O' int value* // class-def id, value list
//           ::= [x60-x6f] value* // class-def id, value list
//
//Object serialization
//
//class Car {
//  String color;
//  String model;
//}
//
//out.writeObject(new Car("red", "corvette"));
//out.writeObject(new Car("green", "civic"));
//
//---
//
//C                        # object definition (#0)
//  x0b example.Car        # type is example.Car
//  x92                    # two fields
//  x05 color              # color field name
//  x05 model              # model field name
//
//O                        # object def (long form)
//  x90                    # object definition #0
//  x03 red                # color field value
//  x08 corvette           # model field value
//
//x60                      # object def #0 (short form)
//  x05 green              # color field value
//  x05 civic              # model field value
//
//
//
//
//
//enum Color {
//  RED,
//  GREEN,
//  BLUE,
//}
//
//out.writeObject(Color.RED);
//out.writeObject(Color.GREEN);
//out.writeObject(Color.BLUE);
//out.writeObject(Color.GREEN);
//
//---
//
//C                         # class definition #0
//  x0b example.Color       # type is example.Color
//  x91                     # one field
//  x04 name                # enumeration field is "name"
//
//x60                       # object #0 (class def #0)
//  x03 RED                 # RED value
//
//x60                       # object #1 (class def #0)
//  x90                     # object definition ref #0
//  x05 GREEN               # GREEN value
//
//x60                       # object #2 (class def #0)
//  x04 BLUE                # BLUE value
//
//x51 x91                   # object ref #1, i.e. Color.GREEN

func (d *Decoder) decClassDef() (interface{}, error) {
	var (
		err       error
		clsName   string
		fieldNum  int32
		fieldName string
		fieldList []string
	)

	clsName, err = d.decString(TAG_READ)
	if err != nil {
		return nil, perrors.WithStack(err)
	}
	fieldNum, err = d.decInt32(TAG_READ)
	if err != nil {
		return nil, perrors.WithStack(err)
	}
	fieldList = make([]string, fieldNum)
	for i := 0; i < int(fieldNum); i++ {
		fieldName, err = d.decString(TAG_READ)
		if err != nil {
			return nil, perrors.Wrapf(err, "decClassDef->decString, field num:%d, index:%d", fieldNum, i)
		}
		fieldList[i] = fieldName
	}

	return &classInfo{javaName: clsName, fieldNameList: fieldList}, nil
}

type fieldInfo struct {
	indexes []int
	field   *reflect.StructField
}

// map[rType][fieldName]indexes
var fieldIndexCache sync.Map

func findFieldWithCache(name string, typ reflect.Type) ([]int, *reflect.StructField, error) {
	typCache, _ := fieldIndexCache.Load(typ)
	if typCache == nil {
		typCache = &sync.Map{}
		fieldIndexCache.Store(typ, typCache)
	}

	iindexes, existCache := typCache.(*sync.Map).Load(name)
	if existCache && iindexes != nil {
		finfo := iindexes.(*fieldInfo)
		var err error
		if len(finfo.indexes) == 0 {
			err = perrors.Errorf("failed to find field %s", name)
		}
		return finfo.indexes, finfo.field, err
	}

	indexes, field, err := findField(name, typ)
	typCache.(*sync.Map).Store(name, &fieldInfo{indexes: indexes, field: field})
	return indexes, field, err
}

// findField find structField in rType
//
// return
// 	indexes []int
// 	field reflect.StructField
// 	err error
func findField(name string, typ reflect.Type) ([]int, *reflect.StructField, error) {
	for i := 0; i < typ.NumField(); i++ {
		// matching tag first, then lowerCamelCase, SameCase, lowerCase

		typField := typ.Field(i)

		tagVal, hasTag := typField.Tag.Lookup(tagIdentifier)

		fieldName := typField.Name
		if hasTag && tagVal == name ||
			fieldName == name ||
			lowerCamelCase(fieldName) == name ||
			strings.ToLower(fieldName) == name {

			return []int{i}, &typField, nil
		}

		if typField.Anonymous && typField.Type.Kind() == reflect.Struct {
			next, field, _ := findField(name, typField.Type)
			if len(next) > 0 {
				indexes := []int{i}
				indexes = append(indexes, next...)

				return indexes, field, nil
			}
		}
	}

	return []int{}, nil, perrors.Errorf("failed to find field %s", name)
}

func (d *Decoder) decInstance(typ reflect.Type, cls *classInfo) (interface{}, error) {
	if typ.Kind() != reflect.Struct {
		return nil, perrors.Errorf("wrong type expect Struct but get:%s", typ.String())
	}

	vRef := reflect.New(typ)
	// add pointer ref so that ref the same object
	d.appendRefs(vRef.Interface())

	vv := vRef.Elem()
	for i := 0; i < len(cls.fieldNameList); i++ {
		fieldName := cls.fieldNameList[i]

		index, fieldStruct, err := findFieldWithCache(fieldName, typ)
		if err != nil {
			d.DecodeValue()
			continue
		}

		// skip unexported anonymous field
		if fieldStruct.PkgPath != "" {
			continue
		}

		field := vv.FieldByIndex(index)
		if !field.CanSet() {
			return nil, perrors.Errorf("decInstance CanSet false for field %s", fieldName)
		}

		// get field type from type object, not do that from value
		fldTyp := UnpackPtrType(field.Type())

		// unpack pointer to enable value setting
		fldRawValue := UnpackPtrValue(field)
		kind := fldTyp.Kind()

		switch kind {
		case reflect.String:
			str, err := d.decString(TAG_READ)
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->ReadString: %s", fieldName)
			}
			fldRawValue.SetString(str)

		case reflect.Int32, reflect.Int16, reflect.Int8:
			num, err := d.decInt32(TAG_READ)
			if err != nil {
				// java enum
				if fldRawValue.Type().Implements(javaEnumType) {
					d.unreadByte() // Enum parsing, decInt64 above has read a byte, so you need to return a byte here
					s, err := d.DecodeValue()
					if err != nil {
						return nil, perrors.Wrapf(err, "decInstance->decObject field name:%s", fieldName)
					}
					enumValue, _ := s.(JavaEnum)
					num = int32(enumValue)
				} else {
					return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
				}
			}
			fldRawValue.SetInt(int64(num))
		case reflect.Uint16, reflect.Uint8:
			num, err := d.decInt32(TAG_READ)
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
			}
			fldRawValue.SetUint(uint64(num))
		case reflect.Uint, reflect.Int, reflect.Int64:
			num, err := d.decInt64(TAG_READ)
			if err != nil {
				if fldTyp.Implements(javaEnumType) {
					d.unreadByte() // Enum parsing, decInt64 above has read a byte, so you need to return a byte here
					s, err := d.Decode()
					if err != nil {
						return nil, perrors.Wrapf(err, "decInstance->decObject field name:%s", fieldName)
					}
					enumValue, _ := s.(JavaEnum)
					num = int64(enumValue)
				} else {
					return nil, perrors.Wrapf(err, "decInstance->decInt64 field name:%s", fieldName)
				}
			}

			fldRawValue.SetInt(num)
		case reflect.Uint32, reflect.Uint64:
			num, err := d.decInt64(TAG_READ)
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->decInt64, field name:%s", fieldName)
			}
			fldRawValue.SetUint(uint64(num))
		case reflect.Bool:
			b, err := d.Decode()
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->Decode field name:%s", fieldName)
			}
			v, ok := b.(bool)
			if !ok {
				return nil, perrors.Wrapf(err, "value convert to bool failed, field name:%s", fieldName)
			}

			if fldRawValue.Kind() == reflect.Ptr && fldRawValue.CanSet() {
				if b != nil {
					field.Set(reflect.ValueOf(&v))
				}
			} else if fldRawValue.Kind() != reflect.Ptr {
				fldRawValue.SetBool(v)
			}

		case reflect.Float32, reflect.Float64:
			num, err := d.decDouble(TAG_READ)
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->decDouble field name:%s", fieldName)
			}
			fldRawValue.SetFloat(num.(float64))

		case reflect.Map:
			// decode map should use the original field value for correct value setting
			err := d.decMapByValue(field)
			if err != nil {
				return nil, perrors.Wrapf(err, "decInstance->decMapByValue field name: %s", fieldName)
			}

		case reflect.Slice, reflect.Array:
			m, err := d.decList(TAG_READ)
			if err != nil {
				if err == io.EOF {
					break
				}
				return nil, perrors.WithStack(err)
			}

			// set slice separately
			err = SetSlice(fldRawValue, m)
			if err != nil {
				return nil, err
			}
		case reflect.Struct:
			var (
				err error
				s   interface{}
			)
			typ := UnpackPtrType(fldRawValue.Type())
			if typ.String() == "time.Time" {
				s, err = d.decDate(TAG_READ)
				if err != nil {
					return nil, perrors.WithStack(err)
				}
				SetValue(fldRawValue, EnsurePackValue(s))
			} else {
				s, err = d.decObject(TAG_READ)
				if err != nil {
					return nil, perrors.WithStack(err)
				}
				if s != nil {
					// set value which accepting pointers
					SetValue(fldRawValue, EnsurePackValue(s))
				}
			}
		case reflect.Interface:
			s, err := d.DecodeValue()
			if err != nil {
				return nil, perrors.WithStack(err)
			}
			if s != nil {
				// set value which accepting pointers
				SetValue(fldRawValue, EnsurePackValue(s))
			}
		default:
			return nil, perrors.Errorf("unknown struct member type: %v %v", kind, typ.Name()+"."+fieldStruct.Name)
		}
	} // end for

	return vRef.Interface(), nil
}

func (d *Decoder) appendClsDef(cd *classInfo) {
	d.classInfoList = append(d.classInfoList, cd)
}

func (d *Decoder) getStructDefByIndex(idx int) (reflect.Type, *classInfo, error) {
	var (
		ok  bool
		cls *classInfo
		s   *structInfo
		err error
	)

	if len(d.classInfoList) <= idx || idx < 0 {
		return nil, cls, perrors.Errorf("illegal class index @idx %d", idx)
	}
	cls = d.classInfoList[idx]
	s, ok = getStructInfo(cls.javaName)
	if !ok {
		// exception
		if s, ok = checkAndGetException(cls); ok {
			return s.typ, cls, nil
		}
		if !d.isSkip {
			err = perrors.Errorf("can not find go type name %s in registry", cls.javaName)
		}
		return nil, cls, err
	}

	return s.typ, cls, nil
}

func (d *Decoder) decEnum(javaName string, flag int32) (JavaEnum, error) {
	var (
		err       error
		enumName  string
		ok        bool
		info      *structInfo
		enumValue JavaEnum
	)
	enumName, err = d.decString(TAG_READ) // java enum class member is "name"
	if err != nil {
		return InvalidJavaEnum, perrors.Wrap(err, "decString for decJavaEnum")
	}
	info, ok = getStructInfo(javaName)
	if !ok {
		return InvalidJavaEnum, perrors.Errorf("getStructInfo(javaName:%s) = false", javaName)
	}

	enumValue = info.inst.(POJOEnum).EnumValue(enumName)
	d.appendRefs(enumValue)
	return enumValue, nil
}

// skip this object
func (d *Decoder) skip(cls *classInfo) error {
	len := len(cls.fieldNameList)
	if len < 1 {
		return nil
	}

	for i := 0; i < len; i++ {
		// skip class fields.
		if _, err := d.DecodeValue(); err != nil {
			return err
		}
	}

	return nil
}

func (d *Decoder) decObject(flag int32) (interface{}, error) {
	var (
		tag byte
		idx int32
		err error
		typ reflect.Type
		cls *classInfo
	)

	if flag != TAG_READ {
		tag = byte(flag)
	} else {
		tag, _ = d.ReadByte()
	}

	switch {
	case tag == BC_NULL:
		return nil, nil
	case tag == BC_REF:
		return d.decRef(int32(tag))
	case tag == BC_OBJECT_DEF:
		clsDef, err := d.decClassDef()
		if err != nil {
			return nil, perrors.Wrap(err, "decObject->decClassDef byte double")
		}
		cls, _ = clsDef.(*classInfo)
		//add to slice
		d.appendClsDef(cls)

		return d.DecodeValue()

	case tag == BC_OBJECT:
		idx, err = d.decInt32(TAG_READ)
		if err != nil {
			return nil, err
		}

		typ, cls, err = d.getStructDefByIndex(int(idx))
		if err != nil {
			return nil, err
		}
		if typ == nil {
			return nil, d.skip(cls)
		}
		if typ.Implements(javaEnumType) {
			return d.decEnum(cls.javaName, TAG_READ)
		}

		if c, ok := GetSerializer(cls.javaName); ok {
			return c.DecObject(d, typ, cls)
		}

		return d.decInstance(typ, cls)

	case BC_OBJECT_DIRECT <= tag && tag <= (BC_OBJECT_DIRECT+OBJECT_DIRECT_MAX):
		typ, cls, err = d.getStructDefByIndex(int(tag - BC_OBJECT_DIRECT))
		if err != nil {
			return nil, err
		}
		if typ == nil {
			return nil, d.skip(cls)
		}
		if typ.Implements(javaEnumType) {
			return d.decEnum(cls.javaName, TAG_READ)
		}

		if c, ok := GetSerializer(cls.javaName); ok {
			return c.DecObject(d, typ, cls)
		}

		return d.decInstance(typ, cls)

	default:
		return nil, perrors.Errorf("decObject illegal object type tag:%+v", tag)
	}
}
