/*
 * 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"
	"strconv"
	"strings"
	"sync"
	"time"
)

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

import (
	"github.com/apache/dubbo-go-hessian2/java_exception"
)

var (
	listTypeNameMapper = &sync.Map{}
	listTypeMapper     = map[string]reflect.Type{
		"string":           reflect.TypeOf(""),
		"java.lang.String": reflect.TypeOf(""),
		"char":             reflect.TypeOf(""),
		"short":            reflect.TypeOf(int32(0)),
		"int":              reflect.TypeOf(int32(0)),
		"long":             reflect.TypeOf(int64(0)),
		"float":            reflect.TypeOf(float64(0)),
		"double":           reflect.TypeOf(float64(0)),
		"boolean":          reflect.TypeOf(true),
		"java.util.Date":   reflect.TypeOf(time.Time{}),
		"date":             reflect.TypeOf(time.Time{}),
		"object":           reflect.TypeOf([]Object{}).Elem(),
		"java.lang.Object": reflect.TypeOf([]Object{}).Elem(),
		// exception field StackTraceElement
		"java.lang.StackTraceElement": reflect.TypeOf([]*java_exception.StackTraceElement{}).Elem(),
	}
)

func init() {
	listTypeNameMapper.Store("string", "[string")
	listTypeNameMapper.Store("int8", "[short")
	listTypeNameMapper.Store("int16", "[short")
	listTypeNameMapper.Store("uint16", "[short")
	listTypeNameMapper.Store("int32", "[int")
	listTypeNameMapper.Store("uint32", "[int")
	listTypeNameMapper.Store("int", "[long")
	listTypeNameMapper.Store("uint", "[long")
	listTypeNameMapper.Store("int64", "[long")
	listTypeNameMapper.Store("uint64", "[long")
	listTypeNameMapper.Store("float32", "[float")
	listTypeNameMapper.Store("float64", "[double")
	listTypeNameMapper.Store("bool", "[boolean")
	listTypeNameMapper.Store("time.Time", "[date")
	listTypeNameMapper.Store("github.com/apache/dubbo-go-hessian2/java_exception/java_exception.Throwabler", "[java.lang.Throwable")

	listTypeNameMapper.Store("github.com/apache/dubbo-go-hessian2/hessian.Object", "[object")
}

func registerListNameMapping(gotype, javaType string) {
	listTypeNameMapper.Store(gotype, "["+javaType)
}

func getListTypeName(goType string) string {
	buf := strings.Builder{}
	count := strings.Count(goType, "[]")
	if count > 0 {
		for i := 1; i < count; i++ {
			buf.WriteString("[")
		}
		goType = strings.Replace(goType, "[]", "", -1)
	}

	v, ok := listTypeNameMapper.Load(goType)
	if !ok {
		v, ok = listTypeNameMapper.Load(strings.TrimPrefix(goType, "*"))
	}

	if ok {
		buf.WriteString(v.(string))
		return buf.String()
	}

	return ""
}

func getListType(javaListName string) reflect.Type {
	javaName := javaListName
	if strings.Index(javaName, "[") == 0 {
		javaName = javaName[1:]
	}
	if strings.Index(javaName, "[") == 0 {
		lt := getListType(javaName)
		if lt == nil {
			return nil
		}
		return reflect.SliceOf(lt)
	}

	var sliceTy reflect.Type
	ltm := listTypeMapper[javaName]
	if ltm != nil {
		sliceTy = reflect.SliceOf(ltm)
	}

	if sliceTy == nil {
		tpStructInfo, _ := getStructInfo(javaName)
		if tpStructInfo == nil || tpStructInfo.typ == nil {
			return nil
		}

		tp := tpStructInfo.typ
		if tp.Kind() != reflect.Ptr {
			tp = reflect.New(tp).Type()
		}
		sliceTy = reflect.SliceOf(tp)
	}
	return sliceTy
}

// Object is equal to Object of java When encoding
type Object interface{}

/////////////////////////////////////////
// List
/////////////////////////////////////////

// encList write list
func (e *Encoder) encList(v interface{}) error {
	if !strings.Contains(reflect.TypeOf(v).String(), "interface {}") {
		return e.writeTypedList(v)
	}
	return e.writeUntypedList(v)
}

// writeTypedList write typed list
// Include 3 formats:
// ::= x55 type value* 'Z'   # variable-length list
// ::= 'V' type int value*   # fixed-length list
// ::= [x70-77] type value*  # fixed-length typed list
func (e *Encoder) writeTypedList(v interface{}) error {
	var err error

	value := reflect.ValueOf(v)
	// https://github.com/apache/dubbo-go-hessian2/issues/317
	// if list is null, just return 'N'
	if value.IsNil() {
		e.buffer = encByte(e.buffer, BC_NULL) // 'N'
		return nil
	}
	// check ref
	if n, ok := e.checkRefMap(value); ok {
		e.buffer = encRef(e.buffer, n)
		return nil
	}

	// try to get list type name of the value type first, for hessian support pointer type.
	// if not found, try to get list type name of the unpacked type.
	typeName := getListTypeName(value.Type().String())
	if typeName == "" {
		value = UnpackPtrValue(value)
		goType := UnpackPtrType(value.Type())
		toType := combineGoTypeName(goType)
		typeName = getListTypeName(toType)
		if typeName == "" {
			return perrors.New("no this type name: " + toType)
		}
	}

	e.buffer = encByte(e.buffer, BC_LIST_FIXED) // 'V'
	e.buffer = encString(e.buffer, typeName)
	e.buffer = encInt32(e.buffer, int32(value.Len()))
	for i := 0; i < value.Len(); i++ {
		if err = e.Encode(value.Index(i).Interface()); err != nil {
			return err
		}
	}

	return nil
}

// writeUntypedList write untyped list
// Include 3 formats:
// ::= x57 value* 'Z'        # variable-length untyped list
// ::= x58 int value*        # fixed-length untyped list
// ::= [x78-7f] value*       # fixed-length untyped list
func (e *Encoder) writeUntypedList(v interface{}) error {
	var err error

	value := reflect.ValueOf(v)

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

	value = UnpackPtrValue(value)

	e.buffer = encByte(e.buffer, BC_LIST_FIXED_UNTYPED) // x58
	e.buffer = encInt32(e.buffer, int32(value.Len()))
	for i := 0; i < value.Len(); i++ {
		if err = e.Encode(value.Index(i).Interface()); err != nil {
			return err
		}
	}

	return nil
}

/////////////////////////////////////////
// List
/////////////////////////////////////////

// # list/vector
// ::= x55 type value* 'Z'   # variable-length list
// ::= 'V' type int value*   # fixed-length list
// ::= x57 value* 'Z'        # variable-length untyped list
// ::= x58 int value*        # fixed-length untyped list
// ::= [x70-77] type value*  # fixed-length typed list
// ::= [x78-7f] value*       # fixed-length untyped list

func (d *Decoder) readBufByte() (byte, error) {
	var (
		err error
		buf [1]byte
	)

	_, err = io.ReadFull(d.reader, buf[:1])
	if err != nil {
		return 0, perrors.WithStack(err)
	}

	return buf[0], nil
}

func listFixedTypedLenTag(tag byte) bool {
	return tag >= _listFixedTypedLenTagMin && tag <= _listFixedTypedLenTagMax
}

// list include 3 formats:
// ::= x55 type value* 'Z'   # variable-length list
// ::= 'V' type int value*   # fixed-length list
// ::= [x70-77] type value*  # fixed-length typed list
func typedListTag(tag byte) bool {
	return tag == BC_LIST_FIXED || tag == BC_LIST_VARIABLE || listFixedTypedLenTag(tag)
}

func listFixedUntypedLenTag(tag byte) bool {
	return tag >= _listFixedUntypedLenTagMin && tag <= _listFixedUntypedLenTagMax
}

// include 3 formats:
// ::= x57 value* 'Z'        # variable-length untyped list
// ::= x58 int value*        # fixed-length untyped list
// ::= [x78-7f] value*       # fixed-length untyped list
func untypedListTag(tag byte) bool {
	return tag == BC_LIST_FIXED_UNTYPED || tag == BC_LIST_VARIABLE_UNTYPED || listFixedUntypedLenTag(tag)
}

// decList read list
func (d *Decoder) decList(flag int32) (interface{}, error) {
	var (
		err error
		tag byte
	)

	if flag != TAG_READ {
		tag = byte(flag)
	} else {
		tag, err = d.ReadByte()
		if err != nil {
			return nil, perrors.WithStack(err)
		}
	}

	switch {
	case tag == BC_NULL:
		return nil, nil
	case tag == BC_REF:
		return d.decRef(int32(tag))
	case typedListTag(tag):
		return d.readTypedList(tag)
	case untypedListTag(tag):
		return d.readUntypedList(tag)
	case binaryTag(tag):
		return d.decBinary(int32(tag))
	default:
		return nil, perrors.Errorf("error list tag: 0x%x", tag)
	}
}

// readTypedList read typed list
// list include 3 formats:
// ::= x55 type value* 'Z'   # variable-length list
// ::= 'V' type int value*   # fixed-length list
// ::= [x70-77] type value*  # fixed-length typed list
func (d *Decoder) readTypedList(tag byte) (interface{}, error) {
	listTyp, err := d.decString(TAG_READ)
	if err != nil {
		return nil, perrors.Errorf("error to read list type[%s]: %v", listTyp, err)
	}

	isVariableArr := tag == BC_LIST_VARIABLE

	var length int
	if listFixedTypedLenTag(tag) {
		length = int(tag - _listFixedTypedLenTagMin)
	} else if tag == BC_LIST_FIXED {
		ii, err := d.decInt32(TAG_READ)
		if err != nil {
			return nil, perrors.WithStack(err)
		}
		length = int(ii)
	} else if isVariableArr {
		length = 0
	} else {
		return nil, perrors.Errorf("error typed list tag: 0x%x", tag)
	}
	if isCollectionSerialize(listTyp) {
		return d.decodeCollection(length, listTyp)
	}
	return d.readTypedListValue(length, listTyp, isVariableArr)
}

func (d *Decoder) readTypedListValue(length int, listTyp string, isVariableArr bool) (interface{}, error) {
	// return when no element
	if length < 0 {
		return nil, nil
	}

	var (
		aryValue reflect.Value
		arrType  reflect.Type
	)

	t, err := strconv.Atoi(listTyp)
	if err == nil {
		// find the ref list type
		arrType = d.typeRefs.Get(t)
		if arrType == nil {
			return nil, perrors.Errorf("can't find ref list type at index %d", t)
		}
		aryValue = reflect.MakeSlice(arrType, length, length)
	} else {
		// try to find the registered list type
		arrType = getListType(listTyp)
		if arrType != nil {
			aryValue = reflect.MakeSlice(arrType, length, length)
			d.typeRefs.appendTypeRefs(listTyp, arrType)
		} else {
			// using default generic list type if not found registered
			aryValue = reflect.ValueOf(make([]interface{}, length, length))
			d.typeRefs.appendTypeRefs(listTyp, aryValue.Type())
		}
	}

	holder := d.appendRefs(aryValue)
	for j := 0; j < length || isVariableArr; j++ {
		it, err := d.DecodeValue()
		if err != nil {
			if perrors.Is(err, io.EOF) && isVariableArr {
				break
			}
			return nil, perrors.WithStack(err)
		}

		if isVariableArr {
			if it != nil {
				aryValue = reflect.Append(aryValue, EnsureRawValue(it))
			} else {
				aryValue = reflect.Append(aryValue, reflect.Zero(aryValue.Type().Elem()))
			}
			holder.change(aryValue)
		} else {
			if it != nil {
				//aryValue.Index(j).Set(EnsureRawValue(it))
				SetValue(aryValue.Index(j), EnsureRawValue(it))
			}
		}
	}

	return holder, nil
}

// readUntypedList read untyped list
// Include 3 formats:
// ::= x57 value* 'Z'        # variable-length untyped list
// ::= x58 int value*        # fixed-length untyped list
// ::= [x78-7f] value*       # fixed-length untyped list
func (d *Decoder) readUntypedList(tag byte) (interface{}, error) {
	isVariableArr := tag == BC_LIST_VARIABLE_UNTYPED

	var length int
	if listFixedUntypedLenTag(tag) {
		length = int(tag - _listFixedUntypedLenTagMin)
	} else if tag == BC_LIST_FIXED_UNTYPED {
		ii, err := d.decInt32(TAG_READ)
		if err != nil {
			return nil, perrors.WithStack(err)
		}
		length = int(ii)
	} else if isVariableArr {
		length = 0
	} else {
		return nil, perrors.Errorf("error untyped list tag: %x", tag)
	}

	ary := make([]interface{}, length)
	aryValue := reflect.ValueOf(ary)
	holder := d.appendRefs(aryValue)

	for j := 0; j < length || isVariableArr; j++ {
		it, err := d.DecodeValue()
		if err != nil {
			if perrors.Is(err, io.EOF) && isVariableArr {
				break
			}
			return nil, perrors.WithStack(err)
		}

		if isVariableArr {
			if it != nil {
				aryValue = reflect.Append(aryValue, EnsureRawValue(it))
			} else {
				aryValue = reflect.Append(aryValue, reflect.Zero(aryValue.Type().Elem()))
			}
			holder.change(aryValue)
		} else {
			ary[j] = EnsureRawAny(it)
		}
	}

	return holder, nil
}
