// Copyright (c) 2016 ~ 2019, Alex Stocks.
//
// 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"
)

import (
	jerrors "github.com/juju/errors"
)

/////////////////////////////////////////
// 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 (e *Encoder) encUntypedList(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
	}

	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, jerrors.Trace(err)
	}

	return buf[0], nil
}

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

// Include 3 formats:
// list ::= 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, jerrors.Trace(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)
	default:
		return nil, jerrors.Errorf("error list tag: 0x%x", tag)
	}
}

// readTypedList read typed list
// Include 3 formats:
// list ::= 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, jerrors.Errorf("error to read list type[%s]: %v", listTyp, err)
	}

	isVariableArr := tag == BC_LIST_VARIABLE

	length := -1
	if listFixedTypedLenTag(tag) {
		length = int(tag - _listFixedTypedLenTagMin)
	} else if tag == BC_LIST_FIXED {
		ii, err := d.decInt32(TAG_READ)
		if err != nil {
			return nil, jerrors.Trace(err)
		}
		length = int(ii)
	} else if isVariableArr {
		length = 0
	} else {
		return nil, jerrors.Errorf("error typed list tag: 0x%x", tag)
	}

	// return when no element
	if length < 0 {
		return nil, nil
	}

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

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

		if it == nil {
			break
		}

		v := EnsureRawValue(it)
		if isVariableArr {
			aryValue = reflect.Append(aryValue, v)
			holder.change(aryValue)
		} else {
			SetValue(aryValue.Index(j), v)
		}
	}

	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, jerrors.Trace(err)
		}
		length = int(ii)
	} else if isVariableArr {
		length = 0
	} else {
		return nil, jerrors.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.Decode()
		if err != nil {
			if err == io.EOF && isVariableArr {
				continue
			}
			return nil, jerrors.Trace(err)
		}

		if isVariableArr {
			aryValue = reflect.Append(aryValue, EnsureRawValue(it))
			holder.change(aryValue)
		} else {
			ary[j] = it
		}
	}

	return holder, nil
}
