// Copyright 2016-2019 Alex Stocks, Wongoo, Yincheng Fang
//
// 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 hessian

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

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 POJO) error {
	var (
		ok     bool
		i      int
		idx    int
		num    int
		err    error
		clsDef classInfo
	)

	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 v.JavaClassName() == 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 {
				idx = RegisterPOJO(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
	}
	num = vv.NumField()
	for i = 0; i < num; i++ {
		// skip unexported anonymous field
		if vv.Type().Field(i).PkgPath != "" {
			continue
		}

		field := vv.Field(i)
		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())
		}
	}

	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
}

func findField(name string, typ reflect.Type) (int, error) {
	for i := 0; i < typ.NumField(); i++ {
		// matching tag first, then lowerCamelCase, SameCase, lowerCase

		if val, has := typ.Field(i).Tag.Lookup(tagIdentifier); has && strings.Compare(val, name) == 0 {
			return i, nil
		}

		fieldName := typ.Field(i).Name
		switch {
		case strings.Compare(lowerCamelCase(fieldName), name) == 0:
			return i, nil
		case strings.Compare(fieldName, name) == 0:
			return i, nil
		case strings.Compare(strings.ToLower(fieldName), name) == 0:
			return i, nil
		}

	}

	return 0, 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, err := findField(fieldName, typ)
		if err != nil {
			return nil, perrors.Errorf("can not find field %s", fieldName)
		}

		// skip unexported anonymous field
		if vv.Type().Field(index).PkgPath != "" {
			continue
		}

		field := vv.Field(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)
			}
			fldRawValue.SetBool(b.(bool))

		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, reflect.Interface:
			var (
				err error
				s   interface{}
			)
			if fldRawValue.Type().String() == "time.Time" {
				s, err = d.decDate(TAG_READ)
				if err != nil {
					return nil, perrors.WithStack(err)
				}
				fldRawValue.Set(reflect.ValueOf(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))
				}
			}

		default:
			return nil, perrors.Errorf("unknown struct member type: %v %v", kind, typ.Name()+"."+typ.Field(index).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
	)

	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 {
		return nil, cls, perrors.Errorf("can not find go type name %s in registry", cls.javaName)
	}

	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
}

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)
		if c, ok := GetSerializer(cls.javaName); ok {
			return c.DecObject(d)
		}
		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.Implements(javaEnumType) {
			return d.decEnum(cls.javaName, TAG_READ)
		}

		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.Implements(javaEnumType) {
			return d.decEnum(cls.javaName, TAG_READ)
		}

		return d.decInstance(typ, cls)

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