/*
 * 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 (
	"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 (
		i      int
		idx    int
		num    int
		err    error
		clsDef *ClassInfo
	)
	pojo, isPojo := v.(POJO)
	// get none pojo JavaClassName
	var nonePojoJavaName string
	if !isPojo {
		s, ok := loadPOJORegistry(v)
		if !ok {
			return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
		}
		nonePojoJavaName = s.javaName
	}

	vv := reflect.ValueOf(v)
	// 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
		}
	}

	var ok bool
	if idx == -1 {
		idx, ok = checkPOJORegistry(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
}

// EncodeMapClass encode a map as object, which MUST contains a key _class and its value is the target class name.
func (e *Encoder) EncodeMapClass(m map[string]interface{}) error {
	clsName, ok := m[ClassKey]
	if !ok {
		return perrors.New("no _class key map")
	}

	className, ok := clsName.(string)
	if !ok {
		return perrors.Errorf("expect string class name, but get %v", reflect.TypeOf(clsName))
	}

	return e.EncodeMapAsClass(className, m)
}

// EncodeMapAsClass encode a map as object of given class name.
func (e *Encoder) EncodeMapAsClass(className string, m map[string]interface{}) error {
	idx := e.classIndex(className)

	if idx == -1 {
		var clsDef *ClassInfo
		s, ok := getStructInfo(className)
		if ok {
			clsDef = pojoRegistry.classInfoList[s.index]
		} else {
			var err error
			clsDef, err = buildMapClassDef(className, m)
			if err != nil {
				return err
			}
		}
		idx = len(e.classInfoList)
		e.classInfoList = append(e.classInfoList, clsDef)
		e.buffer = append(e.buffer, clsDef.buffer...)
	}

	return e.encodeMapAsIndexedClass(idx, m)
}

// EncodeMapAsObject encode a map as the given class defined object.
// Sometimes a class may not being registered in hessian, but it can be decoded from serialized data,
// and the ClassInfo can be found in Decoder by calling Decoder.FindClassInfo.
func (e *Encoder) EncodeMapAsObject(clsDef *ClassInfo, m map[string]interface{}) error {
	idx := e.classIndex(clsDef.javaName)
	if idx == -1 {
		idx = len(e.classInfoList)
		e.classInfoList = append(e.classInfoList, clsDef)
		if len(clsDef.buffer) == 0 {
			clsDef.initDefBuffer()
		}
		e.buffer = append(e.buffer, clsDef.buffer...)
	}
	return e.encodeMapAsIndexedClass(idx, m)
}

// encodeMapAsIndexedClass encode a map as the defined class at the given index in the encoder class list.
func (e *Encoder) encodeMapAsIndexedClass(idx int, m map[string]interface{}) error {
	// 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))
	}

	cls := e.classInfoList[idx]
	var err error
	for i := 0; i < len(cls.fieldNameList); i++ {
		fieldName := cls.fieldNameList[i]
		if err = e.Encode(m[fieldName]); err != nil {
			return perrors.Wrapf(err, "failed to encode field: %s, %+v", fieldName, m[fieldName])
		}
	}
	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 err = d.decToDest(field); err != nil {
			return nil, perrors.Wrapf(err, "decInstance->DecodeValue: %s", fieldName)
		}

	} // 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 && d.Strict {
			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) (interface{}, 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)
	enumVal := PackPtr(reflect.ValueOf(enumValue).Convert(info.typ)).Interface()
	d.appendRefs(enumVal)
	return enumVal, nil
}

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

	for i := 0; i < fieldLen; 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, decErr := d.decClassDef()
		if decErr != nil {
			return nil, perrors.Wrap(decErr, "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 {
			if d.isSkip {
				return nil, d.skip(cls)
			}
			return d.decClassToMap(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 {
			if d.isSkip {
				return nil, d.skip(cls)
			}
			return d.decClassToMap(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)
	}
}

func (d *Decoder) decClassToMap(cls *ClassInfo) (interface{}, error) {
	vMap := make(map[string]interface{}, len(cls.fieldNameList))
	vMap[ClassKey] = cls.javaName

	d.appendRefs(vMap)

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

		fieldValue, decErr := d.DecodeValue()
		if decErr != nil {
			return nil, perrors.Wrapf(decErr, "decClassToMap -> decode field name:%s", fieldName)
		}
		vMap[fieldName] = EnsureRawAny(fieldValue)
	}

	return vMap, nil
}
