/*
 * 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"
)

import (
	gxbytes "github.com/dubbogo/gost/bytes"
	perrors "github.com/pkg/errors"
)

// binaryTag check whether the given tag is a binary tag
func binaryTag(tag byte) bool {
	return (tag >= BC_BINARY_DIRECT && tag <= INT_DIRECT_MAX) ||
		(tag >= BC_BINARY_SHORT && tag <= byte(0x37)) ||
		tag == BC_BINARY_CHUNK ||
		tag == BC_BINARY
}

/////////////////////////////////////////
// Binary, []byte
/////////////////////////////////////////

// # 8-bit binary data split into 64k chunks
// ::= x41(A) b1 b0 <binary-data> binary # non-final chunk
// ::= x42(B) b1 b0 <binary-data>        # final chunk
// ::= [x20-x2f] <binary-data>           # binary data of length 0-15
// ::= [x34-x37] <binary-data>           # binary data of length 0-1023
func encBinary(b []byte, v []byte) []byte {
	var (
		length  uint16
		vLength int
	)

	if v == nil {
		return encByte(b, BC_NULL)
	}

	vLength = len(v)
	for {
		if vLength > CHUNK_SIZE {
			length = CHUNK_SIZE
			b = encByte(b, BC_BINARY_CHUNK, byte(length>>8), byte(length))
		} else {
			length = uint16(vLength)
			if vLength <= int(BINARY_DIRECT_MAX) {
				b = encByte(b, byte(int(BC_BINARY_DIRECT)+vLength))
			} else if vLength <= int(BINARY_SHORT_MAX) {
				b = encByte(b, byte(int(BC_BINARY_SHORT)+vLength>>8), byte(vLength))
			} else {
				b = encByte(b, BC_BINARY, byte(vLength>>8), byte(vLength))
			}
		}

		b = append(b, v[:length]...)
		v = v[length:]
		vLength = len(v)

		if vLength == 0 {
			break
		}
	}

	return b
}

/////////////////////////////////////////
// Binary, []byte
/////////////////////////////////////////

// # 8-bit binary data split into 64k chunks
// ::= x41('A') b1 b0 <binary-data> binary # non-final chunk
// ::= x42('B') b1 b0 <binary-data>        # final chunk
// ::= [x20-x2f] <binary-data>  # binary data of length 0-15
// ::= [x34-x37] <binary-data>  # binary data of length 0-1023
func (d *Decoder) getBinaryLength(tag byte) (int, error) {
	var (
		err error
		buf [2]byte
	)

	if tag >= BC_BINARY_DIRECT && tag <= INT_DIRECT_MAX { // [0x20, 0x2f]
		return int(tag - BC_BINARY_DIRECT), nil
	}

	if tag >= BC_BINARY_SHORT && tag <= byte(0x37) { // [0x34, 0x37]
		_, err = io.ReadFull(d.reader, buf[:1])
		if err != nil {
			return 0, perrors.WithStack(err)
		}

		return int(tag-BC_BINARY_SHORT)<<8 + int(buf[0]), nil
	}

	if tag != BC_BINARY_CHUNK && tag != BC_BINARY {
		return 0, perrors.Errorf("illegal binary tag:%d", tag)
	}

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

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

func (d *Decoder) decBinary(flag int32) ([]byte, error) {
	var (
		err    error
		tag    byte
		length int
	)

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

	if tag == BC_NULL {
		return []byte(""), nil
	}

	data := make([]byte, 0, 128)
	bufp := gxbytes.AcquireBytes(65536)
	defer gxbytes.ReleaseBytes(bufp)
	buf := *bufp

	for {
		length, err = d.getBinaryLength(tag)
		if err != nil {
			return nil, perrors.WithStack(err)
		}

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

		data = append(data, buf[:length]...)

		if tag != BC_BINARY_CHUNK {
			break
		}

		tag, err = d.readBufByte()
		if err != nil {
			return nil, perrors.WithStack(err)
		}
	}
	return data, nil
}
