/*
 * 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 (
	"bufio"
	"bytes"
	"io"
	"reflect"
)

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

// Decoder struct
type Decoder struct {
	reader     *bufio.Reader
	refs       []interface{}
	refHolders []*_refHolder
	// record type refs, both list and map need it
	typeRefs      *TypeRefs
	classInfoList []*ClassInfo
	isSkip        bool

	// In strict mode, a class data can be decoded only when the class is registered, otherwise error returned.
	// In non-strict mode, a class data will be decoded to a map when the class is not registered.
	// The default is non-strict mode, user can change it as required.
	Strict bool
}

// FindClassInfo find ClassInfo for the given name in decoder class info list.
func (d *Decoder) FindClassInfo(javaName string) *ClassInfo {
	for _, info := range d.classInfoList {
		if info.javaName == javaName {
			return info
		}
	}
	return nil
}

// Error part
var (
	ErrNotEnoughBuf    = perrors.Errorf("not enough buf")
	ErrIllegalRefIndex = perrors.Errorf("illegal ref index")
)

// NewDecoder generate a decoder instance
func NewDecoder(b []byte) *Decoder {
	return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), typeRefs: &TypeRefs{records: map[string]bool{}}}
}

// NewStrictDecoder generates a strict mode decoder instance.
// In strict mode, all target class must be registered.
func NewStrictDecoder(b []byte) *Decoder {
	return &Decoder{
		reader:   bufio.NewReader(bytes.NewReader(b)),
		typeRefs: &TypeRefs{records: map[string]bool{}},
		Strict:   true,
	}
}

// NewDecoderSize generate a decoder instance.
func NewDecoderSize(b []byte, size int) *Decoder {
	return &Decoder{reader: bufio.NewReaderSize(bytes.NewReader(b), size), typeRefs: &TypeRefs{records: map[string]bool{}}}
}

// NewDecoderWithSkip generate a decoder instance with skip.
func NewDecoderWithSkip(b []byte) *Decoder {
	return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), typeRefs: &TypeRefs{records: map[string]bool{}}, isSkip: true}
}

// NewCheapDecoderWithSkip generate a decoder instance with skip,
// only for cache pool, before decode Reset should be called.
// For example, with pooling use, will effectively improve performance
//
//		var hessianPool = &sync.Pool{
//			New: func() interface{} {
//				return hessian.NewCheapDecoderWithSkip([]byte{})
//			},
//		}
//
//		decoder := hessianPool.Get().(*hessian.Decoder)
//		fill decode data
//		decoder.Reset(data[:])
//	 decode anything ...
//		hessianPool.Put(decoder)
func NewCheapDecoderWithSkip(b []byte) *Decoder {
	return &Decoder{reader: bufio.NewReader(bytes.NewReader(b)), isSkip: true}
}

// Clean clean the Decoder (room) for a new object decoding.
// Notice it won't reset reader buffer and will continue to read data from it.
func (d *Decoder) Clean() {
	d.typeRefs = &TypeRefs{records: map[string]bool{}}
	d.refs = nil
	d.classInfoList = nil
}

/////////////////////////////////////////
// utilities
/////////////////////////////////////////

func (d *Decoder) Reset(b []byte) *Decoder {
	// reuse reader buf, avoid allocate
	d.reader.Reset(bytes.NewReader(b))
	d.Clean()
	return d
}

// peek a byte
func (d *Decoder) peekByte() byte {
	return d.peek(1)[0]
}

// get the buffer length
func (d *Decoder) len() int {
	d.peek(1) // peek one byte to get the buffer length
	return d.reader.Buffered()
}

// ReadByte read a byte from Decoder, advance the ptr
func (d *Decoder) ReadByte() (byte, error) {
	return d.reader.ReadByte()
}

// Discard skips the next n bytes
func (d *Decoder) Discard(n int) (int, error) {
	return d.reader.Discard(n)
}

// unread a byte
func (d *Decoder) unreadByte() error {
	return d.reader.UnreadByte()
}

// read byte arr, and return the length of b
func (d *Decoder) next(b []byte) (int, error) {
	return d.reader.Read(b)
}

// read byte arr, and return the real length of b
func (d *Decoder) nextFull(b []byte) (int, error) {
	return io.ReadFull(d.reader, b)
}

// peek n bytes, will not advance the read ptr
func (d *Decoder) peek(n int) []byte {
	b, _ := d.reader.Peek(n)
	return b
}

// read utf8 len(s) of array
func (d *Decoder) nextRune(s []rune) []rune {
	var (
		n   int
		i   int
		r   rune
		ri  int
		err error
	)

	n = len(s)
	s = s[:0]
	for i = 0; i < n; i++ {
		if r, ri, err = d.reader.ReadRune(); err == nil && ri > 0 {
			s = append(s, r)
		}
	}

	return s
}

// read the type of data, used to decode list or map
func (d *Decoder) decMapType() (reflect.Type, error) {
	var (
		err     error
		arr     [1]byte
		buf     []byte
		tag     byte
		idx     int32
		typ     reflect.Type
		typName string
	)

	buf = arr[:1]
	if _, err = io.ReadFull(d.reader, buf); err != nil {
		return nil, perrors.WithStack(err)
	}
	tag = buf[0]
	if (tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
		(tag >= 0x30 && tag <= 0x33) || (tag == BC_STRING) || (tag == BC_STRING_CHUNK) {
		typName, err = d.decString(int32(tag))
		if err != nil {
			return nil, perrors.WithStack(err)
		}

		info, ok := getStructInfo(typName)
		if ok {
			typ = info.typ
		} else {
			typ = reflect.TypeOf(map[interface{}]interface{}{})
		}

		// add to type map
		d.typeRefs.appendTypeRefs(typName, typ)

		return typ, nil
	}

	if idx, err = d.decInt32(int32(tag)); err != nil {
		return nil, perrors.WithStack(err)
	}

	typ = d.typeRefs.Get(int(idx))
	if typ == nil {
		return nil, perrors.Errorf("the type ref index %d is out of range", idx)
	}

	return typ, err
}

// Decode parse hessian data, and ensure the reflection value unpacked
func (d *Decoder) Decode() (interface{}, error) {
	v, err := d.DecodeValue()
	if err != nil {
		return nil, err
	}

	for _, holder := range d.refHolders {
		holder.notify()
	}

	return EnsureRawAny(v), nil
}

func (d *Decoder) Buffered() int { return d.reader.Buffered() }

// DecodeValue parse hessian data, the return value maybe a reflection value when it's a map, list, object, or ref.
func (d *Decoder) DecodeValue() (interface{}, error) {
	var (
		err error
		tag byte
	)

	tag, err = d.ReadByte()
	if perrors.Is(err, io.EOF) {
		return nil, err
	}

	switch {
	case tag == BC_END:
		// return EOF error for end flag 'Z'
		return nil, io.EOF

	case tag == BC_NULL: // 'N': //null
		return nil, nil

	case tag == BC_TRUE: // 'T': //true
		return true, nil

	case tag == BC_FALSE: //'F': //false
		return false, nil

	case tag == BC_REF: // 'R': //ref, a int which represents the previous list or map
		return d.decRef(int32(tag))

	case (0x80 <= tag && tag <= 0xbf) || (0xc0 <= tag && tag <= 0xcf) ||
		(0xd0 <= tag && tag <= 0xd7) || tag == BC_INT: //'I': //int
		return d.decInt32(int32(tag))

	case (tag >= 0xd8 && tag <= 0xef) || (tag >= 0xf0 && tag <= 0xff) ||
		(tag >= 0x38 && tag <= 0x3f) || (tag == BC_LONG_INT) || (tag == BC_LONG): //'L': //long
		return d.decInt64(int32(tag))

	case (tag == BC_DATE_MINUTE) || (tag == BC_DATE): //'d': //date
		return d.decDate(int32(tag))

	case (tag == BC_DOUBLE_ZERO) || (tag == BC_DOUBLE_ONE) || (tag == BC_DOUBLE_BYTE) ||
		(tag == BC_DOUBLE_SHORT) || (tag == BC_DOUBLE_MILL) || (tag == BC_DOUBLE): //'D': //double
		return d.decDouble(int32(tag))

	// case 'S', 's', 'X', 'x': //string,xml
	case (tag == BC_STRING_CHUNK || tag == BC_STRING) ||
		(tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
		(tag >= 0x30 && tag <= 0x33):
		return d.decString(int32(tag))

		// case 'B', 'b': //binary
	case (tag == BC_BINARY) || (tag == BC_BINARY_CHUNK) || (tag >= 0x20 && tag <= 0x2f) ||
		(tag >= BC_BINARY_SHORT && tag <= 0x3f):
		return d.decBinary(int32(tag))

	// case 'V': //list
	case (tag >= BC_LIST_DIRECT && tag <= 0x77) || (tag == BC_LIST_FIXED || tag == BC_LIST_VARIABLE) ||
		(tag >= BC_LIST_DIRECT_UNTYPED && tag <= 0x7f) ||
		(tag == BC_LIST_FIXED_UNTYPED || tag == BC_LIST_VARIABLE_UNTYPED):
		return d.decList(int32(tag))

	case (tag == BC_MAP) || (tag == BC_MAP_UNTYPED):
		return d.decMap(int32(tag))

	case (tag == BC_OBJECT_DEF) || (tag == BC_OBJECT) ||
		(BC_OBJECT_DIRECT <= tag && tag <= (BC_OBJECT_DIRECT+OBJECT_DIRECT_MAX)):
		return d.decObject(int32(tag))

	default:
		return nil, perrors.Errorf("Invalid type: %v,>>%v<<<", string(tag), d.peek(d.len()))
	}
}

// decToDest decode data to dest value.
// Before and includes the version v1.12.1, it checks all possible types of the destination,
// and then decode the data according to the type.
// But there are too many cases, and it's impossible to handle all of them.
// After v1.12.1, it decodes the data first, and then set the value to the destination.
// If the destination is map, slice, array, it decodes separately.
func (d *Decoder) decToDest(dest reflect.Value) error {
	destType := dest.Type()
	destRawType := UnpackPtrType(destType)

	// decode for special type, include map, slice, array.
	switch destRawType.Kind() {
	case reflect.Map:
		return d.decMapByValue(dest)
	case reflect.Slice, reflect.Array:
		m, err := d.decList(TAG_READ)
		if err != nil {
			if perrors.Is(err, io.EOF) {
				return nil
			}
			return perrors.WithStack(err)
		}

		return SetSlice(UnpackPtrValue(dest), m)
	}

	dec, err := d.DecodeValue()
	if err != nil {
		return perrors.Wrapf(err, "decToDest: %s", dest.Type().Name())
	}

	// if dec is nil, then return directly.
	if dec == nil {
		return nil
	}

	if ref, ok := dec.(*_refHolder); ok {
		return unpackRefHolder(UnpackPtrValue(dest), destRawType, ref)
	}

	decValue := EnsurePackValue(dec)

	SetValue(dest, decValue)

	return nil
}

// ///////////////////////////////////////
// typeRefs
// ///////////////////////////////////////
type TypeRefs struct {
	typeRefs []reflect.Type
	records  map[string]bool // record if existing for type
}

// appendTypeRefs add list or map type ref
func (t *TypeRefs) appendTypeRefs(name string, p reflect.Type) {
	if t.records[name] {
		return
	}
	t.records[name] = true
	t.typeRefs = append(t.typeRefs, p)
}

func (t *TypeRefs) Get(index int) reflect.Type {
	if len(t.typeRefs) <= index {
		return nil
	}
	return t.typeRefs[index]
}
