// Copyright 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 (
	"encoding/binary"
	"io"
)

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

/////////////////////////////////////////
// Int64
/////////////////////////////////////////

// # 64-bit signed long integer
// ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0
// ::= [xd8-xef]             # -x08 to x0f
// ::= [xf0-xff] b0          # -x800 to x7ff
// ::= [x38-x3f] b1 b0       # -x40000 to x3ffff
// ::= x59 b3 b2 b1 b0       # 32-bit integer cast to long
// hessian-lite/src/main/java/com/alibaba/com/alibaba/com/caucho/hessian/io/Hessian2Output.java:642 WriteLong
func encInt64(b []byte, v int64) []byte {
	if int64(LONG_DIRECT_MIN) <= v && v <= int64(LONG_DIRECT_MAX) {
		return encByte(b, byte(v+int64(BC_LONG_ZERO)))
	} else if int64(LONG_BYTE_MIN) <= v && v <= int64(LONG_BYTE_MAX) {
		return encByte(b, byte(int64(BC_LONG_BYTE_ZERO)+(v>>8)), byte(v))
	} else if int64(LONG_SHORT_MIN) <= v && v <= int64(LONG_SHORT_MAX) {
		return encByte(b, byte(int64(BC_LONG_SHORT_ZERO)+(v>>16)), byte(v>>8), byte(v))
	} else if -0x80000000 <= v && v <= 0x7fffffff {
		return encByte(b, BC_LONG_INT, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
	}

	return encByte(b, 'L', byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}

/////////////////////////////////////////
// Int64
/////////////////////////////////////////

// # 64-bit signed long integer
// ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0
// ::= [xd8-xef]             # -x08 to x0f
// ::= [xf0-xff] b0          # -x800 to x7ff
// ::= [x38-x3f] b1 b0       # -x40000 to x3ffff
// ::= x59 b3 b2 b1 b0       # 32-bit integer cast to long
// ref: hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java:readLong
func (d *Decoder) decInt64(flag int32) (int64, error) {
	var (
		err error
		tag byte
		buf [8]byte
	)

	if flag != TAG_READ {
		tag = byte(flag)
	} else {
		tag, _ = d.readByte()
	}

	switch {
	case tag == BC_NULL:
		return int64(0), nil

	case tag == BC_FALSE:
		return int64(0), nil

	case tag == BC_TRUE:
		return int64(1), nil

		// direct integer
	case tag >= 0x80 && tag <= 0xbf:
		return int64(tag - BC_INT_ZERO), nil

		// byte int
	case tag >= 0xc0 && tag <= 0xcf:
		if _, err = io.ReadFull(d.reader, buf[:1]); err != nil {
			return 0, perrors.WithStack(err)
		}
		return int64(tag-BC_INT_BYTE_ZERO)<<8 + int64(buf[0]), nil

		// short int
	case tag >= 0xd0 && tag <= 0xd7:
		if _, err = io.ReadFull(d.reader, buf[:2]); err != nil {
			return 0, perrors.WithStack(err)
		}
		return int64(tag-BC_INT_SHORT_ZERO)<<16 + int64(buf[0])<<8 + int64(buf[1]), nil

	case tag == BC_DOUBLE_BYTE:
		tag, _ = d.readByte()
		return int64(tag), nil

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

		return int64(int(buf[0])<<8 + int(buf[1])), nil

	case tag == BC_INT: // 'I'
		i32, err := d.decInt32(TAG_READ)
		return int64(i32), err

	case tag == BC_LONG_INT:
		var i32 int32
		err = binary.Read(d.reader, binary.BigEndian, &i32)
		return int64(i32), perrors.WithStack(err)

	case tag >= 0xd8 && tag <= 0xef:
		i8 := int8(tag - BC_LONG_ZERO)
		return int64(i8), nil

	case tag >= 0xf0 && tag <= 0xff:
		buf := []byte{tag - BC_LONG_BYTE_ZERO, 0}
		_, err = io.ReadFull(d.reader, buf[1:])
		if err != nil {
			return 0, perrors.WithStack(err)
		}
		u16 := binary.BigEndian.Uint16(buf)
		i16 := int16(u16)
		return int64(i16), nil

	case tag >= 0x38 && tag <= 0x3f:
		// Use int32 to represent int24.
		buf := []byte{0, tag - BC_LONG_SHORT_ZERO, 0, 0}
		if buf[1]&0x80 != 0 {
			buf[0] = 0xff
		}
		_, err = io.ReadFull(d.reader, buf[2:])
		if err != nil {
			return 0, perrors.WithStack(err)
		}
		u32 := binary.BigEndian.Uint32(buf)
		i32 := int32(u32)
		return int64(i32), nil

	case tag == BC_LONG:
		var i64 int64
		err = binary.Read(d.reader, binary.BigEndian, &i64)
		return i64, perrors.WithStack(err)

	case tag == BC_DOUBLE_ZERO:
		return int64(0), nil

	case tag == BC_DOUBLE_ONE:
		return int64(1), nil

	case tag == BC_DOUBLE_MILL:
		i64, err := d.decInt32(TAG_READ)
		return int64(i64), perrors.WithStack(err)

	default:
		return 0, perrors.Errorf("decInt64 long wrong tag:%#x", tag)
	}
}
